From dae2f6e7d724dd3f20dbd75e91b029ac004e58a9 Mon Sep 17 00:00:00 2001 From: jdcs Date: Thu, 14 Apr 2022 09:50:51 +0200 Subject: [PATCH 001/147] feat: configuration hazelcast with eureka --- pom.xml | 31 ++++++++++-------- .../backend/config/HazelcastConfig.java | 32 +++++++++++++++++++ src/main/resources/eureka-client.properties | 4 +++ 3 files changed, 53 insertions(+), 14 deletions(-) create mode 100644 src/main/java/org/karnak/backend/config/HazelcastConfig.java create mode 100644 src/main/resources/eureka-client.properties diff --git a/pom.xml b/pom.xml index e7d41d779..4891bc999 100644 --- a/pom.xml +++ b/pom.xml @@ -45,11 +45,13 @@ ${java.version} ${java.version} karnak - ${project.basedir}/target/site/jacoco/jacoco.xml + ${project.basedir}/target/site/jacoco/jacoco.xml + jacoco 20211205 1.2.9 - 5.0.2 + 5.1.1 + 2.0.1 4.3.5 5.5.2 @@ -314,12 +316,12 @@ - - verify - - check - - + + + + + + @@ -380,17 +382,18 @@ 1.1.1 + hazelcast-spring com.hazelcast ${hazelcast.version} - - - - - - + + + hazelcast-eureka-one + com.hazelcast + ${hazelcast-eureka-one.version} + liquibase-maven-plugin diff --git a/src/main/java/org/karnak/backend/config/HazelcastConfig.java b/src/main/java/org/karnak/backend/config/HazelcastConfig.java new file mode 100644 index 000000000..b2b924f37 --- /dev/null +++ b/src/main/java/org/karnak/backend/config/HazelcastConfig.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2022 Karnak Team and other contributors. + * + * This program and the accompanying materials are made available under the terms of the Eclipse + * Public License 2.0 which is available at https://www.eclipse.org/legal/epl-2.0, or the Apache + * License, Version 2.0 which is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 + */ +package org.karnak.backend.config; + +import com.hazelcast.config.Config; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class HazelcastConfig { + + @Bean + public Config hazelcastConfiguration() { + Config config = new Config(); + config.getNetworkConfig().getJoin().getMulticastConfig().setEnabled(false); + config + .getNetworkConfig() + .getJoin() + .getEurekaConfig() + .setEnabled(true) + .setProperty("self-registration", "true") + .setProperty("namespace", "hazelcast"); + return config; + } +} diff --git a/src/main/resources/eureka-client.properties b/src/main/resources/eureka-client.properties new file mode 100644 index 000000000..2357808c6 --- /dev/null +++ b/src/main/resources/eureka-client.properties @@ -0,0 +1,4 @@ +hazelcast.shouldUseDns=false +hazelcast.name=hazelcast-karnak +hazelcast.serviceUrl.default=${EUREKA_CLIENT_SERVICE_URL_DEFAULT_ZONE} +#hazelcast.serviceUrl.default=http://localhost:8761/eureka \ No newline at end of file From 73d6107cefbf0e57524f05a119775c5ed1e3f881 Mon Sep 17 00:00:00 2001 From: jdcs Date: Thu, 14 Apr 2022 10:02:24 +0200 Subject: [PATCH 002/147] feat: change deprecated jenkins flow --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 498ca6afc..6d974cab1 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,3 +1,3 @@ @Library('hug-dsi@hugflow') _ import ch.hcuge.dsi.jenkins.BuildImage; -newGenHugFlowMavenPipeline (mavenImage: BuildImage.MVN_36_JDK15) \ No newline at end of file +springBootMavenPipeline (mavenImage: BuildImage.MVN_36_JDK15) \ No newline at end of file From f312865c7664344d4475d101ce20af32e9430061 Mon Sep 17 00:00:00 2001 From: jdcs Date: Thu, 14 Apr 2022 10:10:41 +0200 Subject: [PATCH 003/147] feat: change jenkins flow --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 6d974cab1..b45a343f6 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,3 +1,3 @@ @Library('hug-dsi@hugflow') _ import ch.hcuge.dsi.jenkins.BuildImage; -springBootMavenPipeline (mavenImage: BuildImage.MVN_36_JDK15) \ No newline at end of file +newGenMavenPipeline(mavenImage: BuildImage.MVN_36_JDK15) \ No newline at end of file From 97ba855c3c029c127c9539d98f59eec2c6fc3c4d Mon Sep 17 00:00:00 2001 From: jdcs Date: Thu, 14 Apr 2022 10:17:04 +0200 Subject: [PATCH 004/147] feat: change jenkins flow --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index b45a343f6..b649c44e6 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,3 +1,3 @@ -@Library('hug-dsi@hugflow') _ +@Library('hug-dsi@master') _ import ch.hcuge.dsi.jenkins.BuildImage; newGenMavenPipeline(mavenImage: BuildImage.MVN_36_JDK15) \ No newline at end of file From a1371a40957ff6d4de40aa4bba01d1c8229fc373 Mon Sep 17 00:00:00 2001 From: jdcs Date: Thu, 14 Apr 2022 14:14:14 +0200 Subject: [PATCH 005/147] feat: fix unit tests --- src/main/java/org/karnak/backend/config/HazelcastConfig.java | 2 ++ .../org/karnak/backend/model/editor/DeIdentifyEditorTest.java | 2 ++ .../karnak/backend/service/gateway/GatewaySetUpServiceTest.java | 2 ++ src/test/java/org/karnak/frontend/extid/ExternalIDGridTest.java | 2 ++ src/test/java/org/karnak/profilepipe/ProfileTest.java | 2 ++ 5 files changed, 10 insertions(+) diff --git a/src/main/java/org/karnak/backend/config/HazelcastConfig.java b/src/main/java/org/karnak/backend/config/HazelcastConfig.java index b2b924f37..f35de91e4 100644 --- a/src/main/java/org/karnak/backend/config/HazelcastConfig.java +++ b/src/main/java/org/karnak/backend/config/HazelcastConfig.java @@ -12,11 +12,13 @@ import com.hazelcast.config.Config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; @Configuration public class HazelcastConfig { @Bean + @Profile("!test") public Config hazelcastConfiguration() { Config config = new Config(); config.getNetworkConfig().getJoin().getMulticastConfig().setEnabled(false); diff --git a/src/test/java/org/karnak/backend/model/editor/DeIdentifyEditorTest.java b/src/test/java/org/karnak/backend/model/editor/DeIdentifyEditorTest.java index d4a8f1f12..9fec34f3a 100644 --- a/src/test/java/org/karnak/backend/model/editor/DeIdentifyEditorTest.java +++ b/src/test/java/org/karnak/backend/model/editor/DeIdentifyEditorTest.java @@ -22,10 +22,12 @@ import org.karnak.backend.data.entity.SecretEntity; import org.karnak.backend.enums.PseudonymType; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; import org.weasis.dicom.param.AttributeEditorContext; import org.weasis.dicom.param.DicomNode; @SpringBootTest +@ActiveProfiles("test") class DeIdentifyEditorTest { @Test diff --git a/src/test/java/org/karnak/backend/service/gateway/GatewaySetUpServiceTest.java b/src/test/java/org/karnak/backend/service/gateway/GatewaySetUpServiceTest.java index 32bdf1793..90440fc1c 100644 --- a/src/test/java/org/karnak/backend/service/gateway/GatewaySetUpServiceTest.java +++ b/src/test/java/org/karnak/backend/service/gateway/GatewaySetUpServiceTest.java @@ -36,9 +36,11 @@ import org.karnak.backend.model.event.NodeEvent; import org.mockito.Mockito; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; import org.weasis.dicom.param.DicomNode; @SpringBootTest +@ActiveProfiles("test") class GatewaySetUpServiceTest { // Repositories diff --git a/src/test/java/org/karnak/frontend/extid/ExternalIDGridTest.java b/src/test/java/org/karnak/frontend/extid/ExternalIDGridTest.java index b20edf2da..5bebffd90 100644 --- a/src/test/java/org/karnak/frontend/extid/ExternalIDGridTest.java +++ b/src/test/java/org/karnak/frontend/extid/ExternalIDGridTest.java @@ -20,8 +20,10 @@ import org.karnak.backend.cache.PatientClient; import org.karnak.backend.data.entity.ProjectEntity; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; @SpringBootTest +@ActiveProfiles("test") class ExternalIDGridTest { @Test diff --git a/src/test/java/org/karnak/profilepipe/ProfileTest.java b/src/test/java/org/karnak/profilepipe/ProfileTest.java index 4a14a446f..24a74bfbf 100644 --- a/src/test/java/org/karnak/profilepipe/ProfileTest.java +++ b/src/test/java/org/karnak/profilepipe/ProfileTest.java @@ -26,8 +26,10 @@ import org.karnak.backend.service.profilepipe.Profile; import org.karnak.backend.util.DicomObjectTools; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; @SpringBootTest +@ActiveProfiles("test") class ProfileTest { private static HMAC defaultHMAC; From bdcd1abf012147306b22d0fc8cfc7c7789a858ac Mon Sep 17 00:00:00 2001 From: jdcs Date: Thu, 14 Apr 2022 14:42:02 +0200 Subject: [PATCH 006/147] feat: activate log hazelcast cache for testing purpose --- src/main/java/org/karnak/backend/service/HazelcastService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/karnak/backend/service/HazelcastService.java b/src/main/java/org/karnak/backend/service/HazelcastService.java index d35fa6d43..f520188f0 100644 --- a/src/main/java/org/karnak/backend/service/HazelcastService.java +++ b/src/main/java/org/karnak/backend/service/HazelcastService.java @@ -13,6 +13,7 @@ import org.karnak.backend.config.AppConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; @Service @@ -21,7 +22,7 @@ public class HazelcastService { private static final Logger LOGGER = LoggerFactory.getLogger(HazelcastService.class); /** Log every minutes */ - // @Scheduled(fixedRate = 60000) + @Scheduled(fixedRate = 60000) public void logHazelcast() { LOGGER.info( String.format( From 0457854ee5c78a6d2e4f287bf38aca56f14fc65f Mon Sep 17 00:00:00 2001 From: jdcs Date: Thu, 14 Apr 2022 14:43:53 +0200 Subject: [PATCH 007/147] feat: change pom version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 4891bc999..3e25edd3d 100644 --- a/pom.xml +++ b/pom.xml @@ -16,7 +16,7 @@ - 1.0.3 + 1.0.4 jar From aa65a5088d18b457181e7b4470b88a72595a9ce8 Mon Sep 17 00:00:00 2001 From: jdcs Date: Tue, 19 Apr 2022 15:53:12 +0200 Subject: [PATCH 008/147] feat: test with pom parent --- pom.xml | 85 +- .../java/org/karnak/StartApplication.java | 43 +- .../org/karnak/backend/api/EchoServlet.java | 136 +- .../org/karnak/backend/api/KheopsApi.java | 124 +- .../org/karnak/backend/api/PseudonymApi.java | 585 ++++---- .../org/karnak/backend/api/rqbody/Body.java | 38 +- .../org/karnak/backend/api/rqbody/Data.java | 148 +- .../org/karnak/backend/api/rqbody/Fields.java | 143 +- .../org/karnak/backend/api/rqbody/Ids.java | 21 +- .../karnak/backend/api/rqbody/SearchIds.java | 38 +- .../java/org/karnak/backend/api/utils.java | 25 +- .../karnak/backend/cache/CachedPatient.java | 92 +- .../karnak/backend/cache/ExternalIDCache.java | 12 +- .../backend/cache/MainzellisteCache.java | 12 +- .../backend/cache/MainzellistePatient.java | 78 +- .../org/karnak/backend/cache/Patient.java | 244 ++- .../karnak/backend/cache/PatientClient.java | 81 +- .../backend/cache/PseudonymPatient.java | 14 +- .../karnak/backend/cache/RequestCache.java | 65 +- .../org/karnak/backend/config/AppConfig.java | 203 +-- .../backend/config/DcmProfileConfig.java | 23 +- .../karnak/backend/config/EmailConfig.java | 71 +- .../karnak/backend/config/GatewayConfig.java | 41 +- .../backend/config/HazelcastConfig.java | 24 +- .../backend/config/MainzellisteConfig.java | 78 +- .../config/SecurityInMemoryConfig.java | 137 +- .../config/SecurityOpenIdConnectConfig.java | 175 +-- .../org/karnak/backend/config/WebConfig.java | 17 +- .../org/karnak/backend/constant/EndPoint.java | 22 +- .../karnak/backend/constant/Notification.java | 59 +- .../org/karnak/backend/constant/Token.java | 21 +- .../backend/controller/EchoController.java | 84 +- .../backend/controller/FileController.java | 74 +- .../converter/ArgumentToMapConverter.java | 21 +- .../converter/RectangleListConverter.java | 64 +- .../RectangleListToStringListConverter.java | 28 +- .../TagListToStringListConverter.java | 18 +- .../backend/data/entity/ArgumentEntity.java | 153 +- .../data/entity/DestinationEntity.java | 1311 ++++++++--------- .../data/entity/DicomSourceNodeEntity.java | 256 ++-- .../data/entity/ExcludedTagEntity.java | 12 +- .../data/entity/ForwardNodeEntity.java | 336 ++--- .../data/entity/IncludedTagEntity.java | 12 +- .../data/entity/KheopsAlbumsEntity.java | 219 ++- .../backend/data/entity/MaskEntity.java | 192 +-- .../data/entity/ProfileElementEntity.java | 383 +++-- .../backend/data/entity/ProfileEntity.java | 327 ++-- .../backend/data/entity/ProjectEntity.java | 245 ++- .../data/entity/SOPClassUIDEntity.java | 147 +- .../backend/data/entity/SecretEntity.java | 173 +-- .../karnak/backend/data/entity/TagEntity.java | 118 +- .../data/entity/TransferStatusEntity.java | 893 +++++------ .../backend/data/entity/VersionEntity.java | 76 +- .../backend/data/repo/ArgumentRepo.java | 4 +- .../backend/data/repo/DestinationRepo.java | 4 +- .../data/repo/DicomSourceNodeRepo.java | 4 +- .../backend/data/repo/ForwardNodeRepo.java | 4 +- .../backend/data/repo/KheopsAlbumsRepo.java | 3 +- .../karnak/backend/data/repo/MaskRepo.java | 4 +- .../backend/data/repo/ProfileElementRepo.java | 4 +- .../karnak/backend/data/repo/ProfileRepo.java | 5 +- .../karnak/backend/data/repo/ProjectRepo.java | 4 +- .../backend/data/repo/SOPClassUIDRepo.java | 7 +- .../karnak/backend/data/repo/SecretRepo.java | 4 +- .../org/karnak/backend/data/repo/TagRepo.java | 4 +- .../backend/data/repo/TransferStatusRepo.java | 48 +- .../karnak/backend/data/repo/VersionRepo.java | 12 +- .../TransferStatusSpecification.java | 309 ++-- .../DestinationGroupSequenceProvider.java | 69 +- .../karnak/backend/dicom/DateTimeUtils.java | 594 ++++---- .../org/karnak/backend/dicom/Defacer.java | 304 ++-- .../karnak/backend/dicom/DefacingUtil.java | 194 ++- .../dicom/DicomForwardDestination.java | 212 ++- .../backend/dicom/ForwardDestination.java | 116 +- .../backend/dicom/ForwardDicomNode.java | 146 +- .../karnak/backend/dicom/GatewayParams.java | 45 +- .../backend/dicom/ImageOrientation.java | 455 +++--- .../java/org/karnak/backend/dicom/Params.java | 87 +- .../backend/dicom/WebForwardDestination.java | 168 +-- .../backend/enums/ApplicationProfile.java | 21 +- .../karnak/backend/enums/DestinationType.java | 5 +- .../backend/enums/EnvironmentVariable.java | 27 +- .../karnak/backend/enums/MessageFormat.java | 5 +- .../karnak/backend/enums/MessageLevel.java | 6 +- .../org/karnak/backend/enums/MessageType.java | 7 +- .../org/karnak/backend/enums/Modality.java | 139 +- .../karnak/backend/enums/NodeEventType.java | 6 +- .../karnak/backend/enums/ProfileItemType.java | 120 +- .../karnak/backend/enums/PseudonymType.java | 23 +- .../karnak/backend/enums/SecurityRole.java | 105 +- .../backend/enums/TransferStatusType.java | 55 +- .../org/karnak/backend/enums/UIDType.java | 161 +- .../backend/exception/AbortException.java | 44 +- .../exception/ModuleNotFoundException.java | 7 +- .../exception/SOPNotFoundException.java | 7 +- .../exception/StandardDICOMException.java | 7 +- .../org/karnak/backend/model/FileInfo.java | 58 +- .../java/org/karnak/backend/model/Series.java | 153 +- .../org/karnak/backend/model/SopInstance.java | 117 +- .../org/karnak/backend/model/SourceNode.java | 72 +- .../java/org/karnak/backend/model/Study.java | 245 +-- .../backend/model/action/AbstractAction.java | 180 +-- .../backend/model/action/ActionItem.java | 13 +- .../org/karnak/backend/model/action/Add.java | 40 +- .../backend/model/action/DefaultDummy.java | 42 +- .../org/karnak/backend/model/action/Keep.java | 28 +- .../backend/model/action/MultipleActions.java | 298 ++-- .../karnak/backend/model/action/Remove.java | 30 +- .../karnak/backend/model/action/Replace.java | 46 +- .../backend/model/action/ReplaceNull.java | 31 +- .../org/karnak/backend/model/action/UID.java | 39 +- .../backend/model/dicom/ConfigNode.java | 90 +- .../model/dicom/DicomEchoQueryData.java | 89 +- .../backend/model/dicom/DicomNodeList.java | 51 +- .../karnak/backend/model/dicom/Message.java | 69 +- .../karnak/backend/model/dicom/WadoNode.java | 53 +- .../backend/model/dicom/WadoNodeList.java | 41 +- .../model/dicom/WorkListQueryData.java | 252 ++-- .../dicominnolitics/StandardAttributes.java | 36 +- .../model/dicominnolitics/StandardCIODS.java | 57 +- .../StandardCIODtoModules.java | 57 +- .../StandardConfidentialityProfiles.java | 37 +- .../StandardModuleToAttributes.java | 58 +- .../model/dicominnolitics/StandardSOPS.java | 57 +- .../model/dicominnolitics/jsonAttributes.java | 78 +- .../model/dicominnolitics/jsonCIOD.java | 44 +- .../dicominnolitics/jsonCIODtoModule.java | 55 +- .../jsonConfidentialityProfiles.java | 91 +- .../jsonModuleToAttribute.java | 66 +- .../model/dicominnolitics/jsonSOP.java | 27 +- .../backend/model/echo/DestinationEcho.java | 131 +- .../backend/model/echo/DestinationEchos.java | 19 +- .../backend/model/editor/ConditionEditor.java | 30 +- .../model/editor/DeIdentifyEditor.java | 35 +- .../backend/model/editor/FilterEditor.java | 33 +- .../model/editor/StreamRegistryEditor.java | 204 +-- .../karnak/backend/model/event/NodeEvent.java | 63 +- .../model/event/TransferMonitoringEvent.java | 7 +- .../backend/model/expression/ExprAction.java | 181 +-- .../model/expression/ExprCondition.java | 135 +- .../model/expression/ExpressionError.java | 38 +- .../model/expression/ExpressionItem.java | 4 +- .../model/expression/ExpressionResult.java | 57 +- .../model/kheops/MetadataSwitching.java | 67 +- .../SerieSummaryNotification.java | 173 ++- .../TransferMonitoringNotification.java | 271 ++-- .../backend/model/profilebody/MaskBody.java | 45 +- .../model/profilebody/ProfileElementBody.java | 171 ++- .../model/profilebody/ProfilePipeBody.java | 114 +- .../backend/model/profilepipe/HMAC.java | 212 +-- .../model/profilepipe/HashContext.java | 26 +- .../model/profilepipe/PatientMetadata.java | 175 +-- .../model/profilepipe/TagActionMap.java | 108 +- .../model/profiles/AbstractProfileItem.java | 163 +- .../backend/model/profiles/ActionDates.java | 174 ++- .../backend/model/profiles/ActionTags.java | 154 +- .../backend/model/profiles/BasicProfile.java | 47 +- .../model/profiles/CleanPixelData.java | 19 +- .../backend/model/profiles/Defacing.java | 19 +- .../backend/model/profiles/Expression.java | 99 +- .../backend/model/profiles/PrivateTags.java | 115 +- .../backend/model/profiles/ProfileItem.java | 24 +- .../model/profiles/UpdateUIDsProfile.java | 31 +- .../model/standard/AttributeDetail.java | 106 +- .../model/standard/AttributeDetails.java | 69 +- .../standard/ConfidentialityProfiles.java | 84 +- .../backend/model/standard/DICOMType.java | 51 +- .../karnak/backend/model/standard/Module.java | 45 +- .../model/standard/ModuleAttribute.java | 96 +- .../model/standard/ModuleToAttributes.java | 85 +- .../karnak/backend/model/standard/SOP.java | 71 +- .../karnak/backend/model/standard/SOPS.java | 278 ++-- .../backend/model/standard/StandardDICOM.java | 166 ++- .../security/DefaultIdpLoadCondition.java | 18 +- .../security/OpenIdConnectLogoutHandler.java | 62 +- .../security/UIServiceInitListener.java | 123 +- .../backend/service/CStoreSCPService.java | 285 ++-- .../backend/service/DestinationService.java | 205 ++- .../backend/service/DicomGatewayService.java | 195 ++- .../karnak/backend/service/EchoService.java | 131 +- .../karnak/backend/service/FileService.java | 75 +- .../service/ForwardNodeAPIService.java | 94 +- .../backend/service/ForwardNodeService.java | 229 ++- .../backend/service/ForwardService.java | 1141 +++++++------- .../backend/service/HazelcastService.java | 21 +- .../backend/service/KheopsAlbumsService.java | 144 +- .../backend/service/NotificationService.java | 847 +++++------ .../backend/service/ProjectService.java | 150 +- .../service/PseudonymMappingService.java | 71 +- .../backend/service/SOPClassUIDService.java | 74 +- .../karnak/backend/service/SecretService.java | 53 +- .../backend/service/SourceNodeService.java | 86 +- .../service/StoreScpForwardService.java | 230 +-- .../service/TransferMonitoringService.java | 268 ++-- .../service/dicom/DicomEchoService.java | 54 +- .../backend/service/dicom/WadoService.java | 41 +- .../service/gateway/GatewayService.java | 151 +- .../service/gateway/GatewaySetUpService.java | 798 +++++----- .../service/kheops/SwitchingAlbum.java | 352 ++--- .../profilepipe/AttributesByDefault.java | 101 +- .../backend/service/profilepipe/Profile.java | 594 ++++---- .../profilepipe/ProfilePipeService.java | 224 ++- .../service/profilepipe/Pseudonym.java | 240 ++- .../service/thread/DicomEchoThread.java | 58 +- .../backend/service/thread/WadoResponse.java | 41 +- .../java/org/karnak/backend/util/Counter.java | 30 +- .../org/karnak/backend/util/DateFormat.java | 252 ++-- .../karnak/backend/util/DicomNodeUtil.java | 26 +- .../karnak/backend/util/DicomObjectTools.java | 216 +-- .../util/DoubleToIntegerConverter.java | 37 +- .../backend/util/MetadataDICOMObject.java | 62 +- .../backend/util/NativeLibraryManager.java | 63 +- .../backend/util/PatientClientUtil.java | 93 +- .../backend/util/PrivateTagPattern.java | 4 +- .../org/karnak/backend/util/RandomUtils.java | 129 +- .../org/karnak/backend/util/SecurityUtil.java | 131 +- .../org/karnak/backend/util/ServletUtil.java | 305 ++-- .../org/karnak/backend/util/ShiftDate.java | 195 ++- .../karnak/backend/util/ShiftRangeDate.java | 126 +- .../karnak/backend/util/SpecialCharacter.java | 13 +- .../karnak/backend/util/SpringDocUtil.java | 23 +- .../backend/util/SystemPropertyUtil.java | 37 +- .../java/org/karnak/frontend/AppShell.java | 8 +- .../java/org/karnak/frontend/ErrorView.java | 26 +- .../java/org/karnak/frontend/MainLayout.java | 86 +- src/main/java/org/karnak/frontend/Menu.java | 107 +- .../org/karnak/frontend/about/AboutView.java | 13 +- .../org/karnak/frontend/admin/AdminView.java | 9 +- .../frontend/authentication/CurrentUser.java | 90 +- .../frontend/authentication/LoginScreen.java | 228 ++- .../authentication/NotAuthorizedScreen.java | 99 +- .../frontend/component/AbstractDialog.java | 30 +- .../component/BoxShadowComponent.java | 13 +- .../frontend/component/ConfirmDialog.java | 278 ++-- .../karnak/frontend/component/MessageBox.java | 335 +++-- .../frontend/component/ProfileDropDown.java | 9 +- .../frontend/component/ProjectDropDown.java | 7 +- .../component/WarningConfirmDialog.java | 262 ++-- .../converter/HStringToIntegerConverter.java | 31 +- .../karnak/frontend/dicom/AbstractView.java | 32 +- .../karnak/frontend/dicom/DicomMainView.java | 142 +- .../frontend/dicom/DicomWebToolsBrand.java | 34 +- .../frontend/dicom/FileFormatFilter.java | 233 +-- .../org/karnak/frontend/dicom/PortField.java | 6 +- .../java/org/karnak/frontend/dicom/Util.java | 911 ++++++------ .../frontend/dicom/echo/DicomEchoLogic.java | 58 +- .../dicom/echo/DicomEchoSelectionDialog.java | 483 +++--- .../dicom/echo/DicomEchoSelectionLogic.java | 33 +- .../frontend/dicom/echo/DicomEchoView.java | 676 ++++----- .../frontend/dicom/monitor/MonitorLogic.java | 99 +- .../frontend/dicom/monitor/MonitorView.java | 387 ++--- .../karnak/frontend/dicom/mwl/DicomPane.java | 213 +-- .../frontend/dicom/mwl/DicomPaneLogic.java | 54 +- .../frontend/dicom/mwl/DicomWorkListGrid.java | 94 +- .../dicom/mwl/DicomWorkListLogic.java | 133 +- .../mwl/DicomWorkListSelectionDialog.java | 404 +++-- .../mwl/DicomWorkListSelectionLogic.java | 31 +- .../frontend/dicom/mwl/DicomWorkListView.java | 1002 ++++++------- .../org/karnak/frontend/extid/CSVDialog.java | 421 +++--- .../frontend/extid/DuplicateDialog.java | 68 +- .../karnak/frontend/extid/ExternalIDForm.java | 278 ++-- .../karnak/frontend/extid/ExternalIDGrid.java | 682 ++++----- .../frontend/extid/ExternalIDLogic.java | 31 +- .../karnak/frontend/extid/ExternalIDView.java | 310 ++-- .../karnak/frontend/extid/WarningDialog.java | 48 +- .../forwardnode/ForwardNodeLogic.java | 391 +++-- .../frontend/forwardnode/ForwardNodeView.java | 332 ++--- .../component/GridForwardNode.java | 56 +- .../component/LayoutNewGridForwardNode.java | 83 +- .../forwardnode/component/NewForwardNode.java | 153 +- .../edit/LayoutEditForwardNode.java | 1030 ++++++------- .../component/ButtonSaveDeleteCancel.java | 105 +- .../component/EditAETitleDescription.java | 85 +- .../edit/component/TabSourcesDestination.java | 18 +- .../edit/destination/DestinationLogic.java | 521 +++---- .../edit/destination/DestinationView.java | 289 ++-- .../component/DeIdentificationComponent.java | 678 +++++---- .../component/DeIdentificationName.java | 9 +- .../component/DestinationCondition.java | 83 +- .../component/FilterBySOPClassesForm.java | 82 +- .../edit/destination/component/FormDICOM.java | 253 ++-- .../edit/destination/component/FormSTOW.java | 234 +-- .../component/GridDestination.java | 160 +- .../destination/component/LoadingImage.java | 15 +- .../component/NewUpdateDestination.java | 191 +-- .../component/NotificationComponent.java | 542 ++++--- .../PseudonymInDicomTagComponent.java | 85 +- .../TranscodeOnlyUncompressedComponent.java | 64 +- .../component/TransferSyntaxComponent.java | 64 +- .../component/WarningNoProjectsDefined.java | 80 +- .../forwardnode/edit/source/SourceLogic.java | 194 ++- .../forwardnode/edit/source/SourceView.java | 167 ++- .../edit/source/component/FormSourceNode.java | 76 +- .../edit/source/component/GridSourceNode.java | 22 +- .../source/component/NewUpdateSourceNode.java | 85 +- .../org/karnak/frontend/help/HelpView.java | 54 +- .../org/karnak/frontend/image/LogoKarnak.java | 15 +- .../frontend/kheops/GridSwitchingAlbums.java | 236 ++- .../frontend/kheops/NewSwitchingAlbum.java | 147 +- .../frontend/kheops/SwitchingAlbumsView.java | 192 +-- .../kheops/TextFieldsBindSwitchingAlbum.java | 203 ++- .../mainzelliste/MainzellisteAddPatient.java | 337 ++--- .../mainzelliste/MainzellisteView.java | 20 +- .../frontend/monitoring/MonitoringLogic.java | 103 +- .../frontend/monitoring/MonitoringView.java | 174 +-- .../TransferStatusDataProvider.java | 64 +- .../monitoring/component/ExportSettings.java | 42 +- .../component/ExportSettingsDialog.java | 222 ++- .../component/MonitoringCsvMapping.java | 119 +- .../MonitoringCsvMappingStrategy.java | 28 +- .../component/TransferStatusFilter.java | 143 +- .../component/TransferStatusGrid.java | 814 +++++----- .../TransferStatusGridItemDetail.java | 600 ++++---- .../karnak/frontend/profile/ProfileLogic.java | 262 ++-- .../karnak/frontend/profile/ProfileView.java | 254 ++-- .../profile/component/ProfileGrid.java | 26 +- .../editprofile/ProfileComponent.java | 270 ++-- .../editprofile/ProfileElementMainView.java | 78 +- .../editprofile/ProfileElementView.java | 129 +- .../editprofile/ProfileMasksView.java | 116 +- .../editprofile/ProfileMetadata.java | 201 +-- .../editprofile/ProfileShowHide.java | 90 +- .../editprofile/WarningDeleteProfileUsed.java | 59 +- .../component/errorprofile/ProfileError.java | 58 +- .../errorprofile/ProfileErrorView.java | 116 +- .../karnak/frontend/project/ProjectLogic.java | 338 ++--- .../karnak/frontend/project/ProjectView.java | 263 ++-- .../project/component/EditProject.java | 202 +-- .../project/component/GridProject.java | 49 +- .../project/component/NewProject.java | 86 +- .../project/component/ProjectSecret.java | 100 +- .../component/TextFieldsBindProject.java | 155 +- .../component/WarningRemoveProjectUsed.java | 73 +- .../mapping/PseudonymMappingLogic.java | 144 +- .../mapping/PseudonymMappingView.java | 353 +++-- .../component/MappingInputComponent.java | 84 +- .../component/MappingResultComponent.java | 244 ++- .../frontend/util/NotificationUtil.java | 26 +- .../frontend/util/ToggleButtonTheme.java | 77 +- .../java/org/karnak/frontend/util/UIS.java | 29 +- src/main/resources/application.yml | 32 +- .../karnak/backend/api/PseudonymApiTest.java | 99 +- .../cache/MainzellistePatientTest.java | 278 ++-- .../backend/cache/PatientClientUtilTest.java | 150 +- .../controller/EchoControllerTest.java | 124 +- .../backend/data/repo/ArgumentRepoTest.java | 258 ++-- .../data/repo/DestinationRepoTest.java | 237 ++- .../data/repo/DicomSourceNodeRepoTest.java | 231 ++- .../data/repo/ForwardNodeRepoTest.java | 765 +++++----- .../data/repo/KheopsAlbumsRepoTest.java | 329 +++-- .../backend/data/repo/MaskRepoTest.java | 251 ++-- .../data/repo/ProfileElementRepoTest.java | 245 +-- .../backend/data/repo/ProfileRepoTest.java | 323 ++-- .../backend/data/repo/ProjectRepoTest.java | 229 ++- .../data/repo/SOPClassUIDRepoTest.java | 229 ++- .../backend/data/repo/SecretRepoTest.java | 284 ++-- .../karnak/backend/data/repo/TagRepoTest.java | 261 ++-- .../data/repo/TransferStatusRepoTest.java | 373 +++-- .../TransferStatusSpecificationTest.java | 392 +++-- .../backend/dicom/ForwardDestinationTest.java | 169 ++- .../karnak/backend/dicom/ForwardUtilTest.java | 164 +-- .../backend/enums/ProfileItemTypeTest.java | 88 +- .../karnak/backend/model/action/AddTest.java | 21 +- .../backend/model/action/ReplaceTest.java | 55 +- .../model/echo/DestinationEchoTest.java | 29 +- .../model/editor/DeIdentifyEditorTest.java | 70 +- .../model/editor/FilterEditorTest.java | 125 +- .../editor/StreamRegistryEditorTest.java | 143 +- .../model/profiles/TagPatternProfileTest.java | 169 ++- .../model/profiles/UpdateUIDsProfileTest.java | 85 +- .../service/DestinationServiceTest.java | 144 +- .../backend/service/EchoServiceTest.java | 87 +- .../service/ForwardNodeAPIServiceTest.java | 176 ++- .../service/ForwardNodeServiceTest.java | 349 +++-- .../service/KheopsAlbumsServiceTest.java | 184 ++- .../service/NotificationServiceTest.java | 159 +- .../backend/service/ProjectServiceTest.java | 207 ++- .../service/SOPClassUIDServiceTest.java | 75 +- .../backend/service/SecretServiceTest.java | 77 +- .../service/SourceNodeServiceTest.java | 136 +- .../TransferMonitoringServiceTest.java | 210 ++- .../service/gateway/GatewayService.java | 4 +- .../gateway/GatewaySetUpServiceTest.java | 535 ++++--- .../kheops/SwitchingAlbumServiceTest.java | 288 ++-- .../profilepipe/AttributesByDefaultTest.java | 71 +- .../profilepipe/ProfilePipeServiceTest.java | 176 +-- .../service/profilepipe/ProfileTest.java | 279 ++-- .../component/ProjectDropDownTest.java | 15 +- .../org/karnak/frontend/dicom/UtilTest.java | 175 ++- .../karnak/frontend/extid/CSVDialogTest.java | 23 +- .../frontend/extid/ExternalIDGridTest.java | 141 +- .../frontend/extid/ExternalIDLogicTest.java | 50 +- .../component/GridDestinationTest.java | 15 +- .../ProfileElementMainViewTest.java | 79 +- .../mapping/PseudonymMappingLogicTest.java | 111 +- .../component/MappingInputComponentTest.java | 19 +- .../component/MappingResultComponentTest.java | 55 +- .../org/karnak/kheops/ExprConditionTest.java | 493 +++---- .../org/karnak/profilepipe/ProfileTest.java | 1115 +++++++------- .../option/datemanager/DatePatternTest.java | 61 +- .../option/datemanager/ShiftDateTest.java | 370 ++--- .../datemanager/ShiftRangeDateTest.java | 250 ++-- .../profilepipe/utils/ExprDCMElemTest.java | 49 +- .../karnak/profilepipe/utils/HMACTest.java | 489 +++--- .../utils/PatientMetadataTest.java | 398 +++-- 405 files changed, 30533 insertions(+), 32121 deletions(-) diff --git a/pom.xml b/pom.xml index 3e25edd3d..9c3bf59a3 100644 --- a/pom.xml +++ b/pom.xml @@ -3,6 +3,15 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + + + + ch.hcuge.springcloud + spring-cloud-ms-dependencies + 2.6.6-2021.0.1-1.0 + + + karnak ${project.artifactId} 4.0.0 @@ -286,44 +295,44 @@ com.vaadin ${vaadin.version} - - com.diffplug.spotless - spotless-maven-plugin - 2.17.7 - - - - - - @formatter:off - @formatter:on - - - - -/* - * Copyright (c) $YEAR Karnak Team and other contributors. - * - * This program and the accompanying materials are made available under the terms of the Eclipse - * Public License 2.0 which is available at https://www.eclipse.org/legal/epl-2.0, or the Apache - * License, Version 2.0 which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 - */ - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/java/org/karnak/StartApplication.java b/src/main/java/org/karnak/StartApplication.java index 9cb49ac9d..096c48273 100644 --- a/src/main/java/org/karnak/StartApplication.java +++ b/src/main/java/org/karnak/StartApplication.java @@ -34,31 +34,30 @@ @EnableAsync public class StartApplication implements CommandLineRunner { - private static final Logger log = LoggerFactory.getLogger(StartApplication.class); + private static final Logger log = LoggerFactory.getLogger(StartApplication.class); - @Autowired(required = false) - private AppConfig myConfig; + @Autowired(required = false) + private AppConfig myConfig; - public static void main(String[] args) { - SpringApplicationBuilder application = new SpringApplicationBuilder(StartApplication.class); + public static void main(String[] args) { + SpringApplicationBuilder application = new SpringApplicationBuilder(StartApplication.class); - // If environment variable IDP exists and has value "oidc": activate the profile - // application-oidc.yml - if (System.getenv().containsKey(EnvironmentVariable.IDP.getCode()) - && Objects.equals( - System.getenv().get(EnvironmentVariable.IDP.getCode()), - ApplicationProfile.OIDC.getCode())) { - application.profiles(ApplicationProfile.OIDC.getCode()); - } + // If environment variable IDP exists and has value "oidc": activate the profile + // application-oidc.yml + if (System.getenv().containsKey(EnvironmentVariable.IDP.getCode()) && Objects + .equals(System.getenv().get(EnvironmentVariable.IDP.getCode()), ApplicationProfile.OIDC.getCode())) { + application.profiles(ApplicationProfile.OIDC.getCode()); + } - // Run application - application.run(args); - } + // Run application + application.run(args); + } + + @Override + public void run(String... args) { + log.info("StartApplication..."); + log.info("using environment: " + (myConfig != null ? myConfig.getEnvironment() : "")); + log.info("name: " + (myConfig != null ? myConfig.getName() : "")); + } - @Override - public void run(String... args) { - log.info("StartApplication..."); - log.info("using environment: " + (myConfig != null ? myConfig.getEnvironment() : "")); - log.info("name: " + (myConfig != null ? myConfig.getName() : "")); - } } diff --git a/src/main/java/org/karnak/backend/api/EchoServlet.java b/src/main/java/org/karnak/backend/api/EchoServlet.java index 816f6dc1d..08ba82c83 100644 --- a/src/main/java/org/karnak/backend/api/EchoServlet.java +++ b/src/main/java/org/karnak/backend/api/EchoServlet.java @@ -37,73 +37,79 @@ @WebServlet(urlPatterns = "/echo") public class EchoServlet extends HttpServlet { - @Serial private static final long serialVersionUID = -8349040600894140520L; - private static final Logger LOGGER = LoggerFactory.getLogger(EchoServlet.class); + @Serial + private static final long serialVersionUID = -8349040600894140520L; - @Autowired private GatewaySetUpService globalConfig; + private static final Logger LOGGER = LoggerFactory.getLogger(EchoServlet.class); - @Override - public final void init() throws ServletException { - if (globalConfig == null) { - LOGGER.error("EchoServlet service cannot start: GatewaySetUpService is missing."); - destroy(); - } - } + @Autowired + private GatewaySetUpService globalConfig; - @Override - public void doGet(HttpServletRequest req, HttpServletResponse res) { - res.setContentType("text/xml"); - PrintWriter out = null; - try { - out = res.getWriter(); - } catch (IOException e) { - String errorMsg = "Cannot write response"; - LOGGER.error(errorMsg); - ServletUtil.sendResponseError(res, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, errorMsg); - return; - } - String aet = req.getParameter("srcAET"); - if (globalConfig == null) { - String errorMsg = "Missing 'GlobalConfig' from current ServletContext"; - LOGGER.error(errorMsg); - ServletUtil.sendResponseError(res, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, errorMsg); - return; - } - // Echo service, only work for the out stream configuration - AdvancedParams params = new AdvancedParams(); - ConnectOptions connectOptions = new ConnectOptions(); - connectOptions.setConnectTimeout(3000); - connectOptions.setAcceptTimeout(5000); - params.setConnectOptions(connectOptions); - StringBuilder sb = new StringBuilder(""); + @Override + public final void init() throws ServletException { + if (globalConfig == null) { + LOGGER.error("EchoServlet service cannot start: GatewaySetUpService is missing."); + destroy(); + } + } + + @Override + public void doGet(HttpServletRequest req, HttpServletResponse res) { + res.setContentType("text/xml"); + PrintWriter out = null; + try { + out = res.getWriter(); + } + catch (IOException e) { + String errorMsg = "Cannot write response"; + LOGGER.error(errorMsg); + ServletUtil.sendResponseError(res, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, errorMsg); + return; + } + String aet = req.getParameter("srcAET"); + if (globalConfig == null) { + String errorMsg = "Missing 'GlobalConfig' from current ServletContext"; + LOGGER.error(errorMsg); + ServletUtil.sendResponseError(res, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, errorMsg); + return; + } + // Echo service, only work for the out stream configuration + AdvancedParams params = new AdvancedParams(); + ConnectOptions connectOptions = new ConnectOptions(); + connectOptions.setConnectTimeout(3000); + connectOptions.setAcceptTimeout(5000); + params.setConnectOptions(connectOptions); + StringBuilder sb = new StringBuilder(""); + + Optional srcNode = globalConfig.getDestinationNode(aet); + if (srcNode.isPresent()) { + List list = globalConfig.getDestinations(srcNode.get()); + for (ForwardDestination val : list) { + if (val instanceof DicomForwardDestination) { + DicomNode calledNode = ((DicomForwardDestination) val).getStreamSCU().getCalledNode(); + // TODO isUseAetDest + DicomState dicomState = Echo.process(params, srcNode.get(), calledNode); + sb.append(""); + sb.append(dicomState.getStatus()); + sb.append("\n"); + } + else if (val instanceof WebForwardDestination) { + WebForwardDestination d = (WebForwardDestination) val; + sb.append(""); + // To implement + // sb.append(d.getStowRS().); + sb.append("\n"); + } + } + } + sb.append("\n"); + out.println(sb); + } - Optional srcNode = globalConfig.getDestinationNode(aet); - if (srcNode.isPresent()) { - List list = globalConfig.getDestinations(srcNode.get()); - for (ForwardDestination val : list) { - if (val instanceof DicomForwardDestination) { - DicomNode calledNode = ((DicomForwardDestination) val).getStreamSCU().getCalledNode(); - // TODO isUseAetDest - DicomState dicomState = Echo.process(params, srcNode.get(), calledNode); - sb.append(""); - sb.append(dicomState.getStatus()); - sb.append("\n"); - } else if (val instanceof WebForwardDestination) { - WebForwardDestination d = (WebForwardDestination) val; - sb.append(""); - // To implement - // sb.append(d.getStowRS().); - sb.append("\n"); - } - } - } - sb.append("\n"); - out.println(sb); - } } diff --git a/src/main/java/org/karnak/backend/api/KheopsApi.java b/src/main/java/org/karnak/backend/api/KheopsApi.java index 6f5895db8..a1d53b714 100644 --- a/src/main/java/org/karnak/backend/api/KheopsApi.java +++ b/src/main/java/org/karnak/backend/api/KheopsApi.java @@ -30,80 +30,66 @@ @Service public class KheopsApi { - private final HttpClient httpClient; - private final String X_AUTHORIZATION_SOURCE = "X-Authorization-Source"; + private final HttpClient httpClient; - private static final Logger LOGGER = LoggerFactory.getLogger(KheopsApi.class); + private final String X_AUTHORIZATION_SOURCE = "X-Authorization-Source"; - @Autowired - public KheopsApi() { - httpClient = - HttpClient.newBuilder() // one instance, reuse - .version(HttpClient.Version.HTTP_1_1) - .build(); - } + private static final Logger LOGGER = LoggerFactory.getLogger(KheopsApi.class); - // https://github.com/OsiriX-Foundation/KheopsAuthorization/wiki/Add-a-series - // /studies/{StudyInstanceIUD}/series/{SeriesInstanceIUD}/albums/{album_id} - // album_id: album id destination - // x-authorization-source: main album token - // Authorization: album destination token - public int shareSerie( - String studyInstanceUID, - String seriesInstanceUID, - String API_URL, - String authorizationSource, - String authorizationDestination) - throws IOException, InterruptedException { - final String stringURI = - String.format("%s/studies/%s/series/%s", API_URL, studyInstanceUID, seriesInstanceUID); - final URI uri = URI.create(stringURI); - HttpRequest request = - HttpRequest.newBuilder() - .PUT(HttpRequest.BodyPublishers.noBody()) - .uri(uri) - .setHeader(HttpHeaders.ACCEPT, "application/json") - .setHeader(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded") - .setHeader( - HttpHeaders.AUTHORIZATION, String.format("Bearer %s", authorizationDestination)) - .setHeader(X_AUTHORIZATION_SOURCE, String.format("Bearer %s", authorizationSource)) - .build(); + @Autowired + public KheopsApi() { + httpClient = HttpClient.newBuilder() // one instance, reuse + .version(HttpClient.Version.HTTP_1_1).build(); + } - HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); - try { - return response.statusCode(); - } catch (Exception e) { - System.err.println(e); - } - return -1; - } + // https://github.com/OsiriX-Foundation/KheopsAuthorization/wiki/Add-a-series + // /studies/{StudyInstanceIUD}/series/{SeriesInstanceIUD}/albums/{album_id} + // album_id: album id destination + // x-authorization-source: main album token + // Authorization: album destination token + public int shareSerie(String studyInstanceUID, String seriesInstanceUID, String API_URL, String authorizationSource, + String authorizationDestination) throws IOException, InterruptedException { + final String stringURI = String.format("%s/studies/%s/series/%s", API_URL, studyInstanceUID, seriesInstanceUID); + final URI uri = URI.create(stringURI); + HttpRequest request = HttpRequest.newBuilder().PUT(HttpRequest.BodyPublishers.noBody()).uri(uri) + .setHeader(HttpHeaders.ACCEPT, "application/json") + .setHeader(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded") + .setHeader(HttpHeaders.AUTHORIZATION, String.format("Bearer %s", authorizationDestination)) + .setHeader(X_AUTHORIZATION_SOURCE, String.format("Bearer %s", authorizationSource)).build(); - public JSONObject tokenIntrospect( - String API_URL, String authorizationToken, String introspectToken) - throws IOException, InterruptedException { - final String stringURI = String.format("%s/token/introspect", API_URL); - final URI uri = URI.create(stringURI); + HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); + try { + return response.statusCode(); + } + catch (Exception e) { + System.err.println(e); + } + return -1; + } - Map data = new HashMap<>(); - data.put("token", introspectToken); - HttpRequest request = - HttpRequest.newBuilder() - .POST(utils.buildDataFromMap(data)) - .uri(uri) - .setHeader(HttpHeaders.ACCEPT, "application/json") - .setHeader(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded") - .setHeader(HttpHeaders.AUTHORIZATION, String.format("Bearer %s", authorizationToken)) - .build(); + public JSONObject tokenIntrospect(String API_URL, String authorizationToken, String introspectToken) + throws IOException, InterruptedException { + final String stringURI = String.format("%s/token/introspect", API_URL); + final URI uri = URI.create(stringURI); + + Map data = new HashMap<>(); + data.put("token", introspectToken); + HttpRequest request = HttpRequest.newBuilder().POST(utils.buildDataFromMap(data)).uri(uri) + .setHeader(HttpHeaders.ACCEPT, "application/json") + .setHeader(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded") + .setHeader(HttpHeaders.AUTHORIZATION, String.format("Bearer %s", authorizationToken)).build(); + + HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); + try { + final int status = response.statusCode(); + if (status >= 200 && status <= 300) { + return new JSONObject(response.body()); + } + } + catch (Exception e) { + System.err.println(e); + } + return new JSONObject(); + } - HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); - try { - final int status = response.statusCode(); - if (status >= 200 && status <= 300) { - return new JSONObject(response.body()); - } - } catch (Exception e) { - System.err.println(e); - } - return new JSONObject(); - } } diff --git a/src/main/java/org/karnak/backend/api/PseudonymApi.java b/src/main/java/org/karnak/backend/api/PseudonymApi.java index aabfcd4b9..38f9b6568 100644 --- a/src/main/java/org/karnak/backend/api/PseudonymApi.java +++ b/src/main/java/org/karnak/backend/api/PseudonymApi.java @@ -39,307 +39,286 @@ /** API model */ public class PseudonymApi { - private static final Logger LOGGER = LoggerFactory.getLogger(PseudonymApi.class); - - private static final String SERVER_URL = MainzellisteConfig.getInstance().getServerurl(); - private static final String API_KEY = MainzellisteConfig.getInstance().getApikey(); - - private static final String MAINZELLISTE_HEADER = "mainzellisteApiKey"; - private static final String CONTENT_TYPE_HEADER = "Content-Type"; - - private final HttpClient httpClient = - HttpClient.newBuilder() // one instance, reuse - .version(HttpClient.Version.HTTP_1_1) - .build(); - - private String sessionId; - - public String addExtID(Fields patientFields, String externalPseudonym) { - this.sessionId = rqGetSessionId(true); - String[] extid = {"pid", "extid"}; - Data data = new Data(extid, patientFields, new Ids(externalPseudonym)); - try { - return getPseudonym(data); - } catch (Exception e) { - throw new IllegalStateException( - String.format("Cannot add a extid %s in Mainzellise %s", externalPseudonym, e)); - } - } - - public String getExistingExtID(Fields patientFields) { - this.sessionId = rqGetSessionId(true); - String[] extid = {"pid", "extid"}; - Data data = new Data(extid, patientFields, null); - try { - return getPseudonym(data); - } catch (Exception e) { - throw new IllegalStateException("Cannot get an existing extid in Mainzelliste API", e); - } - } - - public String generatePID(Fields patientFields) { - this.sessionId = rqGetSessionId(true); - String[] extid = {"pid"}; - Data data = new Data(extid, patientFields, null); - try { - return getPseudonym(data); - } catch (Exception e) { - throw new IllegalStateException("Cannot generate pid in Mainzelliste", e); - } - } - - public JSONArray searchPatient(String pseudonym, String idTypes) { - this.sessionId = rqGetSessionId(false); - SearchIds[] searchIds = {new SearchIds(idTypes, pseudonym)}; // search example - return getPatients(searchIds, false); - } - - private String getPseudonym(Data data) throws IOException { - String tokenIDAddPatient; - try { - tokenIDAddPatient = rqCreateTokenAddPatient(data); - List pseudonymList = rqCreatePatient(tokenIDAddPatient); - String idTypes = data.get_idtypes()[data.get_idtypes().length - 1]; - JSONObject jsonPseudonym = - pseudonymList.stream() - .filter(p -> p.getString("idType").equals(idTypes)) - .findFirst() - .orElseThrow(); - return jsonPseudonym.getString("idString"); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new IOException(e); - } - } - - /*** - * This classe allow the communcation betwen karnak and pseudonym api with a specific sessionId - * @param sessionsId - * public PseudonymApi(String sessionsId) { - * this.sessionId = sessionsId; - * } - */ - - /*** - * This method allow to construct a body in BodyPublisher format - * @param data This param is the body in format HashMap with Key Value - * @return BodyPublisher with the content of the data to pass in the body - */ - private static HttpRequest.BodyPublisher buildFormDataFromMap(Map data) { - var builder = new StringBuilder(); - for (Map.Entry entry : data.entrySet()) { - if (entry != null) { - if (builder.length() > 0) { - builder.append("&"); - } - builder.append(URLEncoder.encode(entry.getKey().toString(), StandardCharsets.UTF_8)); - builder.append("="); - builder.append(URLEncoder.encode(entry.getValue().toString(), StandardCharsets.UTF_8)); - } - } - - return HttpRequest.BodyPublishers.ofString(builder.toString()); - } - - /*** - * Get patient in pseudonym api - * @param searchIds - * @param shouldThrowException Check if an exception should be thrown or only a log - * @return Pseudonym - */ - private JSONArray getPatients(SearchIds[] searchIds, boolean shouldThrowException) { - JSONArray patientArray = null; - try { - String tokenId = rqCreateTokenReadPatient(searchIds, shouldThrowException); - patientArray = rqGetPatient(tokenId, shouldThrowException); - } catch (InterruptedException e) { - LOGGER.warn("Session interrupted. Cannot create patient", e); - Thread.currentThread().interrupt(); - } catch (Exception e) { - LOGGER.info("Cannot get patient", e); - } - return patientArray; - } - - /*** - * Make the request to have an id session to the API that manages the pseudonyms - * @param shouldThrowException Check if an exception should be thrown or only a log - * @return sessionID - */ - private String rqGetSessionId(boolean shouldThrowException) { - Map data = new HashMap<>(); - HttpRequest request = - HttpRequest.newBuilder() - .POST(buildFormDataFromMap(data)) - .uri(URI.create(SERVER_URL + "/sessions")) - .header(CONTENT_TYPE_HEADER, MediaType.APPLICATION_JSON_VALUE) - .header(MAINZELLISTE_HEADER, API_KEY) - .build(); - - HttpResponse response; - try { - response = httpClient.send(request, BodyHandlers.ofString()); - if (controlErrorResponse(response, shouldThrowException)) { - JSONObject jsonResp = new JSONObject(response.body()); - this.sessionId = jsonResp.getString("sessionId"); - } - } catch (InterruptedException e) { - LOGGER.warn("Session interrupted with Mainzelliste API", e); - Thread.currentThread().interrupt(); - } catch (Exception e) { - LOGGER.error("Cannot get a sessionId with Mainzelliste API", e); - } - return this.sessionId; - } - - /*** - * Make the request to have a token that allow to add a new patient - * @return sessionID - */ - private String rqCreateTokenAddPatient(Data data) throws IOException, InterruptedException { - Body bodyRequest = new Body("addPatient", data); - Gson gson = new Gson(); - String jsonBody = gson.toJson(bodyRequest); - - HttpRequest request = - HttpRequest.newBuilder() - .POST(BodyPublishers.ofString(jsonBody)) - .uri(URI.create(SERVER_URL + "/sessions/" + this.sessionId + "/tokens")) - .header(CONTENT_TYPE_HEADER, MediaType.APPLICATION_JSON_VALUE) - .header(MAINZELLISTE_HEADER, API_KEY) - .build(); - - final HttpResponse response = httpClient.send(request, BodyHandlers.ofString()); - controlErrorResponse(response, true); - final JSONObject jsonResp = new JSONObject(response.body()); - return jsonResp.getString("tokenId"); - } - - /*** - * Make the request to have a token that allow to get patient(s) - * @param searchIds - * @param shouldThrowException Check if an exception should be thrown or only a log - * @return Patients - */ - private String rqCreateTokenReadPatient(SearchIds[] searchIds, boolean shouldThrowException) - throws IOException, InterruptedException { - String tokenId = null; - String jsonBody = createJsonReadPatient(searchIds); - HttpRequest request = - HttpRequest.newBuilder() - .POST(BodyPublishers.ofString(jsonBody)) - .uri(URI.create(SERVER_URL + "/sessions/" + this.sessionId + "/tokens")) - .header(CONTENT_TYPE_HEADER, MediaType.APPLICATION_JSON_VALUE) - .header(MAINZELLISTE_HEADER, API_KEY) - .build(); - - HttpResponse response = httpClient.send(request, BodyHandlers.ofString()); - if (controlErrorResponse(response, shouldThrowException)) { - JSONObject jsonResp = new JSONObject(response.body()); - tokenId = jsonResp.getString("tokenId"); - } - - return tokenId; - } - - /*** - * Make the request to create patient with the tokenId - * @param tokenId - * @return Pseudonym - */ - private List rqCreatePatient(String tokenId) - throws IOException, InterruptedException { - Map data = new HashMap<>(); - data.put("sureness", true); - HttpRequest request = - HttpRequest.newBuilder() - .POST(buildFormDataFromMap(data)) - .uri( - URI.create( - SERVER_URL + "/patients?tokenId=" + tokenId + "&mainzellisteApiVersion=2.0")) - .header(CONTENT_TYPE_HEADER, MediaType.APPLICATION_FORM_URLENCODED_VALUE) - .header(MAINZELLISTE_HEADER, API_KEY) - .build(); - - List newIds = new ArrayList<>(); - HttpResponse response = httpClient.send(request, BodyHandlers.ofString()); - controlErrorResponse(response, true); - JSONArray jsonResp = new JSONArray(response.body()); - for (Object o : jsonResp) { - if (o instanceof JSONObject) { - newIds.add((JSONObject) o); - } - } - - return newIds; - } - - /*** - * Make the request to get patient with the tokenId - * @param tokenId - * @param shouldThrowException Check if an exception should be thrown or only a log - * @return Pseudonym - */ - private JSONArray rqGetPatient(String tokenId, boolean shouldThrowException) - throws IOException, InterruptedException { - JSONArray jsonArray = null; - - HttpRequest request = - HttpRequest.newBuilder() - .GET() - .uri(URI.create(SERVER_URL + "/patients?tokenId=" + tokenId)) - .header(CONTENT_TYPE_HEADER, MediaType.APPLICATION_FORM_URLENCODED_VALUE) - .header(MAINZELLISTE_HEADER, API_KEY) - .build(); - - HttpResponse response = httpClient.send(request, BodyHandlers.ofString()); - if (controlErrorResponse(response, shouldThrowException)) { - jsonArray = new JSONArray(response.body()); - } - return jsonArray; - } - - /*** - * This method allow to create a json body for readPatients in pseudonym api - * @param searchIds SearchIds that we want to read in pseudonym api. - * @return String json body - */ - private String createJsonReadPatient(SearchIds[] searchIds) { - String[] resultFields = { - "patientID", "patientName", "patientBirthDate", "patientSex", "issuerOfPatientID" - }; // fields returns - Data data = new Data(searchIds, resultFields); - - Body bodyRequest = new Body("readPatients", data); - Gson gson = new Gson(); - return gson.toJson(bodyRequest); - } - - /** - * Control response - * - * @param response Response - * @param throwError should an exception should be thrown - * @return true if no problem in response, false otherwise - */ - private boolean controlErrorResponse(HttpResponse response, boolean throwError) { - boolean status = true; - if (response.statusCode() >= HttpURLConnection.HTTP_BAD_REQUEST) { - final String errorMsg = - "\n\tMainzelliste response : " - + "\n\t\tstatus code: " - + response.statusCode() - + "\n\t\theaders:: " - + response.headers() - + "\n\t\tbody: " - + response.body(); - if (throwError) { - throw new IllegalStateException(errorMsg); - } else { - LOGGER.info(errorMsg); - status = false; - } - } - return status; - } + private static final Logger LOGGER = LoggerFactory.getLogger(PseudonymApi.class); + + private static final String SERVER_URL = MainzellisteConfig.getInstance().getServerurl(); + + private static final String API_KEY = MainzellisteConfig.getInstance().getApikey(); + + private static final String MAINZELLISTE_HEADER = "mainzellisteApiKey"; + + private static final String CONTENT_TYPE_HEADER = "Content-Type"; + + private final HttpClient httpClient = HttpClient.newBuilder() // one instance, reuse + .version(HttpClient.Version.HTTP_1_1).build(); + + private String sessionId; + + public String addExtID(Fields patientFields, String externalPseudonym) { + this.sessionId = rqGetSessionId(true); + String[] extid = { "pid", "extid" }; + Data data = new Data(extid, patientFields, new Ids(externalPseudonym)); + try { + return getPseudonym(data); + } + catch (Exception e) { + throw new IllegalStateException( + String.format("Cannot add a extid %s in Mainzellise %s", externalPseudonym, e)); + } + } + + public String getExistingExtID(Fields patientFields) { + this.sessionId = rqGetSessionId(true); + String[] extid = { "pid", "extid" }; + Data data = new Data(extid, patientFields, null); + try { + return getPseudonym(data); + } + catch (Exception e) { + throw new IllegalStateException("Cannot get an existing extid in Mainzelliste API", e); + } + } + + public String generatePID(Fields patientFields) { + this.sessionId = rqGetSessionId(true); + String[] extid = { "pid" }; + Data data = new Data(extid, patientFields, null); + try { + return getPseudonym(data); + } + catch (Exception e) { + throw new IllegalStateException("Cannot generate pid in Mainzelliste", e); + } + } + + public JSONArray searchPatient(String pseudonym, String idTypes) { + this.sessionId = rqGetSessionId(false); + SearchIds[] searchIds = { new SearchIds(idTypes, pseudonym) }; // search example + return getPatients(searchIds, false); + } + + private String getPseudonym(Data data) throws IOException { + String tokenIDAddPatient; + try { + tokenIDAddPatient = rqCreateTokenAddPatient(data); + List pseudonymList = rqCreatePatient(tokenIDAddPatient); + String idTypes = data.get_idtypes()[data.get_idtypes().length - 1]; + JSONObject jsonPseudonym = pseudonymList.stream().filter(p -> p.getString("idType").equals(idTypes)) + .findFirst().orElseThrow(); + return jsonPseudonym.getString("idString"); + } + catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new IOException(e); + } + } + + /*** + * This classe allow the communcation betwen karnak and pseudonym api with a specific + * sessionId + * @param sessionsId public PseudonymApi(String sessionsId) { this.sessionId = + * sessionsId; } + */ + + /*** + * This method allow to construct a body in BodyPublisher format + * @param data This param is the body in format HashMap with Key Value + * @return BodyPublisher with the content of the data to pass in the body + */ + private static HttpRequest.BodyPublisher buildFormDataFromMap(Map data) { + var builder = new StringBuilder(); + for (Map.Entry entry : data.entrySet()) { + if (entry != null) { + if (builder.length() > 0) { + builder.append("&"); + } + builder.append(URLEncoder.encode(entry.getKey().toString(), StandardCharsets.UTF_8)); + builder.append("="); + builder.append(URLEncoder.encode(entry.getValue().toString(), StandardCharsets.UTF_8)); + } + } + + return HttpRequest.BodyPublishers.ofString(builder.toString()); + } + + /*** + * Get patient in pseudonym api + * @param searchIds + * @param shouldThrowException Check if an exception should be thrown or only a log + * @return Pseudonym + */ + private JSONArray getPatients(SearchIds[] searchIds, boolean shouldThrowException) { + JSONArray patientArray = null; + try { + String tokenId = rqCreateTokenReadPatient(searchIds, shouldThrowException); + patientArray = rqGetPatient(tokenId, shouldThrowException); + } + catch (InterruptedException e) { + LOGGER.warn("Session interrupted. Cannot create patient", e); + Thread.currentThread().interrupt(); + } + catch (Exception e) { + LOGGER.info("Cannot get patient", e); + } + return patientArray; + } + + /*** + * Make the request to have an id session to the API that manages the pseudonyms + * @param shouldThrowException Check if an exception should be thrown or only a log + * @return sessionID + */ + private String rqGetSessionId(boolean shouldThrowException) { + Map data = new HashMap<>(); + HttpRequest request = HttpRequest.newBuilder().POST(buildFormDataFromMap(data)) + .uri(URI.create(SERVER_URL + "/sessions")).header(CONTENT_TYPE_HEADER, MediaType.APPLICATION_JSON_VALUE) + .header(MAINZELLISTE_HEADER, API_KEY).build(); + + HttpResponse response; + try { + response = httpClient.send(request, BodyHandlers.ofString()); + if (controlErrorResponse(response, shouldThrowException)) { + JSONObject jsonResp = new JSONObject(response.body()); + this.sessionId = jsonResp.getString("sessionId"); + } + } + catch (InterruptedException e) { + LOGGER.warn("Session interrupted with Mainzelliste API", e); + Thread.currentThread().interrupt(); + } + catch (Exception e) { + LOGGER.error("Cannot get a sessionId with Mainzelliste API", e); + } + return this.sessionId; + } + + /*** + * Make the request to have a token that allow to add a new patient + * @return sessionID + */ + private String rqCreateTokenAddPatient(Data data) throws IOException, InterruptedException { + Body bodyRequest = new Body("addPatient", data); + Gson gson = new Gson(); + String jsonBody = gson.toJson(bodyRequest); + + HttpRequest request = HttpRequest.newBuilder().POST(BodyPublishers.ofString(jsonBody)) + .uri(URI.create(SERVER_URL + "/sessions/" + this.sessionId + "/tokens")) + .header(CONTENT_TYPE_HEADER, MediaType.APPLICATION_JSON_VALUE).header(MAINZELLISTE_HEADER, API_KEY) + .build(); + + final HttpResponse response = httpClient.send(request, BodyHandlers.ofString()); + controlErrorResponse(response, true); + final JSONObject jsonResp = new JSONObject(response.body()); + return jsonResp.getString("tokenId"); + } + + /*** + * Make the request to have a token that allow to get patient(s) + * @param searchIds + * @param shouldThrowException Check if an exception should be thrown or only a log + * @return Patients + */ + private String rqCreateTokenReadPatient(SearchIds[] searchIds, boolean shouldThrowException) + throws IOException, InterruptedException { + String tokenId = null; + String jsonBody = createJsonReadPatient(searchIds); + HttpRequest request = HttpRequest.newBuilder().POST(BodyPublishers.ofString(jsonBody)) + .uri(URI.create(SERVER_URL + "/sessions/" + this.sessionId + "/tokens")) + .header(CONTENT_TYPE_HEADER, MediaType.APPLICATION_JSON_VALUE).header(MAINZELLISTE_HEADER, API_KEY) + .build(); + + HttpResponse response = httpClient.send(request, BodyHandlers.ofString()); + if (controlErrorResponse(response, shouldThrowException)) { + JSONObject jsonResp = new JSONObject(response.body()); + tokenId = jsonResp.getString("tokenId"); + } + + return tokenId; + } + + /*** + * Make the request to create patient with the tokenId + * @param tokenId + * @return Pseudonym + */ + private List rqCreatePatient(String tokenId) throws IOException, InterruptedException { + Map data = new HashMap<>(); + data.put("sureness", true); + HttpRequest request = HttpRequest.newBuilder().POST(buildFormDataFromMap(data)) + .uri(URI.create(SERVER_URL + "/patients?tokenId=" + tokenId + "&mainzellisteApiVersion=2.0")) + .header(CONTENT_TYPE_HEADER, MediaType.APPLICATION_FORM_URLENCODED_VALUE) + .header(MAINZELLISTE_HEADER, API_KEY).build(); + + List newIds = new ArrayList<>(); + HttpResponse response = httpClient.send(request, BodyHandlers.ofString()); + controlErrorResponse(response, true); + JSONArray jsonResp = new JSONArray(response.body()); + for (Object o : jsonResp) { + if (o instanceof JSONObject) { + newIds.add((JSONObject) o); + } + } + + return newIds; + } + + /*** + * Make the request to get patient with the tokenId + * @param tokenId + * @param shouldThrowException Check if an exception should be thrown or only a log + * @return Pseudonym + */ + private JSONArray rqGetPatient(String tokenId, boolean shouldThrowException) + throws IOException, InterruptedException { + JSONArray jsonArray = null; + + HttpRequest request = HttpRequest.newBuilder().GET() + .uri(URI.create(SERVER_URL + "/patients?tokenId=" + tokenId)) + .header(CONTENT_TYPE_HEADER, MediaType.APPLICATION_FORM_URLENCODED_VALUE) + .header(MAINZELLISTE_HEADER, API_KEY).build(); + + HttpResponse response = httpClient.send(request, BodyHandlers.ofString()); + if (controlErrorResponse(response, shouldThrowException)) { + jsonArray = new JSONArray(response.body()); + } + return jsonArray; + } + + /*** + * This method allow to create a json body for readPatients in pseudonym api + * @param searchIds SearchIds that we want to read in pseudonym api. + * @return String json body + */ + private String createJsonReadPatient(SearchIds[] searchIds) { + String[] resultFields = { "patientID", "patientName", "patientBirthDate", "patientSex", "issuerOfPatientID" }; // fields + // returns + Data data = new Data(searchIds, resultFields); + + Body bodyRequest = new Body("readPatients", data); + Gson gson = new Gson(); + return gson.toJson(bodyRequest); + } + + /** + * Control response + * @param response Response + * @param throwError should an exception should be thrown + * @return true if no problem in response, false otherwise + */ + private boolean controlErrorResponse(HttpResponse response, boolean throwError) { + boolean status = true; + if (response.statusCode() >= HttpURLConnection.HTTP_BAD_REQUEST) { + final String errorMsg = "\n\tMainzelliste response : " + "\n\t\tstatus code: " + response.statusCode() + + "\n\t\theaders:: " + response.headers() + "\n\t\tbody: " + response.body(); + if (throwError) { + throw new IllegalStateException(errorMsg); + } + else { + LOGGER.info(errorMsg); + status = false; + } + } + return status; + } + } diff --git a/src/main/java/org/karnak/backend/api/rqbody/Body.java b/src/main/java/org/karnak/backend/api/rqbody/Body.java index 8c7c342cb..41e2903ba 100644 --- a/src/main/java/org/karnak/backend/api/rqbody/Body.java +++ b/src/main/java/org/karnak/backend/api/rqbody/Body.java @@ -11,27 +11,29 @@ public class Body { - private String type; - private Data data; + private String type; - public Body(String type, Data data) { - this.type = type; - this.data = data; - } + private Data data; - public String get_type() { - return this.type; - } + public Body(String type, Data data) { + this.type = type; + this.data = data; + } - public void set_type(String type) { - this.type = type; - } + public String get_type() { + return this.type; + } - public Data get_data() { - return this.data; - } + public void set_type(String type) { + this.type = type; + } + + public Data get_data() { + return this.data; + } + + public void set_data(Data data) { + this.data = data; + } - public void set_data(Data data) { - this.data = data; - } } diff --git a/src/main/java/org/karnak/backend/api/rqbody/Data.java b/src/main/java/org/karnak/backend/api/rqbody/Data.java index a2a16c880..62c28f70c 100644 --- a/src/main/java/org/karnak/backend/api/rqbody/Data.java +++ b/src/main/java/org/karnak/backend/api/rqbody/Data.java @@ -11,75 +11,81 @@ public class Data { - private String[] idtypes; - private Fields fields; - private Ids ids; - private SearchIds[] searchIds; - private String[] resultFields; - private String[] resultIds; - - public Data(String[] idtypes, Fields fields, Ids ids) { - this.idtypes = idtypes; - this.fields = fields; - this.ids = ids; - } - - public Data(SearchIds[] searchIds, String[] resultFields, String[] resultIds) { - this.searchIds = searchIds; - this.resultFields = resultFields; - this.resultIds = resultIds; - } - - public Data(SearchIds[] searchIds, String[] resultFields) { - this.searchIds = searchIds; - this.resultFields = resultFields; - } - - public String[] get_idtypes() { - return this.idtypes; - } - - public void set_idtypes(String[] idtypes) { - this.idtypes = idtypes; - } - - public Fields get_fields() { - return this.fields; - } - - public void set_fields(Fields fields) { - this.fields = fields; - } - - public Ids get_ids() { - return this.ids; - } - - public void set_ids(Ids ids) { - this.ids = ids; - } - - public SearchIds[] get_searchIds() { - return this.searchIds; - } - - public void set_searchIds(SearchIds[] searchIds) { - this.searchIds = searchIds; - } - - public String[] get_resultFields() { - return this.resultFields; - } - - public void set_resultFields(String[] resultFields) { - this.resultFields = resultFields; - } - - public String[] get_resultIds() { - return this.resultIds; - } - - public void set_resultIds(String[] resultIds) { - this.resultIds = resultIds; - } + private String[] idtypes; + + private Fields fields; + + private Ids ids; + + private SearchIds[] searchIds; + + private String[] resultFields; + + private String[] resultIds; + + public Data(String[] idtypes, Fields fields, Ids ids) { + this.idtypes = idtypes; + this.fields = fields; + this.ids = ids; + } + + public Data(SearchIds[] searchIds, String[] resultFields, String[] resultIds) { + this.searchIds = searchIds; + this.resultFields = resultFields; + this.resultIds = resultIds; + } + + public Data(SearchIds[] searchIds, String[] resultFields) { + this.searchIds = searchIds; + this.resultFields = resultFields; + } + + public String[] get_idtypes() { + return this.idtypes; + } + + public void set_idtypes(String[] idtypes) { + this.idtypes = idtypes; + } + + public Fields get_fields() { + return this.fields; + } + + public void set_fields(Fields fields) { + this.fields = fields; + } + + public Ids get_ids() { + return this.ids; + } + + public void set_ids(Ids ids) { + this.ids = ids; + } + + public SearchIds[] get_searchIds() { + return this.searchIds; + } + + public void set_searchIds(SearchIds[] searchIds) { + this.searchIds = searchIds; + } + + public String[] get_resultFields() { + return this.resultFields; + } + + public void set_resultFields(String[] resultFields) { + this.resultFields = resultFields; + } + + public String[] get_resultIds() { + return this.resultIds; + } + + public void set_resultIds(String[] resultIds) { + this.resultIds = resultIds; + } + } diff --git a/src/main/java/org/karnak/backend/api/rqbody/Fields.java b/src/main/java/org/karnak/backend/api/rqbody/Fields.java index 2f4aab32e..8b59a367c 100644 --- a/src/main/java/org/karnak/backend/api/rqbody/Fields.java +++ b/src/main/java/org/karnak/backend/api/rqbody/Fields.java @@ -11,75 +11,76 @@ public class Fields { - // --------------------------------------------------------------- - // Fields ------------------------------------------------------- - // --------------------------------------------------------------- - private String patientID; - private String patientName; - private String patientBirthDate; - private String patientSex; - private String issuerOfPatientID; - - // --------------------------------------------------------------- - // Constructors ------------------------------------------------ - // --------------------------------------------------------------- - public Fields(String patientID) { - this.patientID = patientID; - } - - public Fields( - String patientID, - String patientName, - String patientBirthDate, - String patientSex, - String issuerOfPatientID) { - this.patientID = patientID; - this.patientName = patientName; - this.patientBirthDate = patientBirthDate; - this.patientSex = patientSex; - this.issuerOfPatientID = issuerOfPatientID; - } - - // --------------------------------------------------------------- - // Getters/Setters ------------------------------------------------ - // --------------------------------------------------------------- - public String get_patientID() { - return this.patientID; - } - - public void set_patientID(String patientID) { - this.patientID = patientID; - } - - public String get_patientName() { - return this.patientName; - } - - public void set_patientName(String patientName) { - this.patientName = patientName; - } - - public String get_patientBirthDate() { - return this.patientBirthDate; - } - - public void set_patientBirthDate(String patientBirthDate) { - this.patientBirthDate = patientBirthDate; - } - - public String get_patientSex() { - return this.patientSex; - } - - public void set_patientSex(String patientSex) { - this.patientSex = patientSex; - } - - public String get_issuerOfPatientID() { - return this.issuerOfPatientID; - } - - public void set_issuerOfPatientID(String issuerOfPatientID) { - this.issuerOfPatientID = issuerOfPatientID; - } + // --------------------------------------------------------------- + // Fields ------------------------------------------------------- + // --------------------------------------------------------------- + private String patientID; + + private String patientName; + + private String patientBirthDate; + + private String patientSex; + + private String issuerOfPatientID; + + // --------------------------------------------------------------- + // Constructors ------------------------------------------------ + // --------------------------------------------------------------- + public Fields(String patientID) { + this.patientID = patientID; + } + + public Fields(String patientID, String patientName, String patientBirthDate, String patientSex, + String issuerOfPatientID) { + this.patientID = patientID; + this.patientName = patientName; + this.patientBirthDate = patientBirthDate; + this.patientSex = patientSex; + this.issuerOfPatientID = issuerOfPatientID; + } + + // --------------------------------------------------------------- + // Getters/Setters ------------------------------------------------ + // --------------------------------------------------------------- + public String get_patientID() { + return this.patientID; + } + + public void set_patientID(String patientID) { + this.patientID = patientID; + } + + public String get_patientName() { + return this.patientName; + } + + public void set_patientName(String patientName) { + this.patientName = patientName; + } + + public String get_patientBirthDate() { + return this.patientBirthDate; + } + + public void set_patientBirthDate(String patientBirthDate) { + this.patientBirthDate = patientBirthDate; + } + + public String get_patientSex() { + return this.patientSex; + } + + public void set_patientSex(String patientSex) { + this.patientSex = patientSex; + } + + public String get_issuerOfPatientID() { + return this.issuerOfPatientID; + } + + public void set_issuerOfPatientID(String issuerOfPatientID) { + this.issuerOfPatientID = issuerOfPatientID; + } + } diff --git a/src/main/java/org/karnak/backend/api/rqbody/Ids.java b/src/main/java/org/karnak/backend/api/rqbody/Ids.java index c679fbe59..20722bc0a 100644 --- a/src/main/java/org/karnak/backend/api/rqbody/Ids.java +++ b/src/main/java/org/karnak/backend/api/rqbody/Ids.java @@ -11,17 +11,18 @@ public class Ids { - private String extid; + private String extid; - public Ids(String extid) { - this.extid = extid; - } + public Ids(String extid) { + this.extid = extid; + } - public String get_extid() { - return this.extid; - } + public String get_extid() { + return this.extid; + } + + public void set_extid(String extid) { + this.extid = extid; + } - public void set_extid(String extid) { - this.extid = extid; - } } diff --git a/src/main/java/org/karnak/backend/api/rqbody/SearchIds.java b/src/main/java/org/karnak/backend/api/rqbody/SearchIds.java index 7d7cc3c92..adbb0e48b 100644 --- a/src/main/java/org/karnak/backend/api/rqbody/SearchIds.java +++ b/src/main/java/org/karnak/backend/api/rqbody/SearchIds.java @@ -11,27 +11,29 @@ public class SearchIds { - private String idType; - private String idString; + private String idType; - public SearchIds(String idType, String idString) { - this.idType = idType; - this.idString = idString; - } + private String idString; - public String get_idType() { - return this.idType; - } + public SearchIds(String idType, String idString) { + this.idType = idType; + this.idString = idString; + } - public void set_idType(String idType) { - this.idType = idType; - } + public String get_idType() { + return this.idType; + } - public String get_idString() { - return this.idString; - } + public void set_idType(String idType) { + this.idType = idType; + } + + public String get_idString() { + return this.idString; + } + + public void set_idString(String idString) { + this.idString = idString; + } - public void set_idString(String idString) { - this.idString = idString; - } } diff --git a/src/main/java/org/karnak/backend/api/utils.java b/src/main/java/org/karnak/backend/api/utils.java index 1d7289c5c..84c3f4123 100644 --- a/src/main/java/org/karnak/backend/api/utils.java +++ b/src/main/java/org/karnak/backend/api/utils.java @@ -16,16 +16,17 @@ public class utils { - public static HttpRequest.BodyPublisher buildDataFromMap(Map data) { - var builder = new StringBuilder(); - for (Map.Entry entry : data.entrySet()) { - if (builder.length() > 0) { - builder.append("&"); - } - builder.append(URLEncoder.encode(entry.getKey().toString(), StandardCharsets.UTF_8)); - builder.append("="); - builder.append(URLEncoder.encode(entry.getValue().toString(), StandardCharsets.UTF_8)); - } - return HttpRequest.BodyPublishers.ofString(builder.toString()); - } + public static HttpRequest.BodyPublisher buildDataFromMap(Map data) { + var builder = new StringBuilder(); + for (Map.Entry entry : data.entrySet()) { + if (builder.length() > 0) { + builder.append("&"); + } + builder.append(URLEncoder.encode(entry.getKey().toString(), StandardCharsets.UTF_8)); + builder.append("="); + builder.append(URLEncoder.encode(entry.getValue().toString(), StandardCharsets.UTF_8)); + } + return HttpRequest.BodyPublishers.ofString(builder.toString()); + } + } diff --git a/src/main/java/org/karnak/backend/cache/CachedPatient.java b/src/main/java/org/karnak/backend/cache/CachedPatient.java index 6e37f739f..beacdaf79 100644 --- a/src/main/java/org/karnak/backend/cache/CachedPatient.java +++ b/src/main/java/org/karnak/backend/cache/CachedPatient.java @@ -11,52 +11,48 @@ public class CachedPatient extends Patient { - private Long projectID; - - public CachedPatient( - String pseudonym, - String patientId, - String patientFirstName, - String patientLastName, - String issuerOfPatientId, - Long projectID) { - super(pseudonym, patientId, patientFirstName, patientLastName, null, null, issuerOfPatientId); - this.projectID = projectID; - } - - public void setPseudonym(String pseudonym) { - this.pseudonym = pseudonym; - } - - public void setPatientId(String patientId) { - this.patientId = patientId; - } - - public void setPatientFirstName(String patientFirstName) { - updatePatientFirstName(patientFirstName); - } - - public void setPatientLastName(String patientLastName) { - updatePatientLastName(patientLastName); - } - - public void setIssuerOfPatientId(String issuerOfPatientId) { - this.issuerOfPatientId = issuerOfPatientId; - } - - public Long getProjectID() { - return projectID; - } - - public void setProjectID(Long projectID) { - this.projectID = projectID; - } - - @Override - public String toString() { - return String.format( - "External pseudonym: %s, Patient ID: %s, Patient first name: %s, Patient last name: %s," - + " Issuer of patient ID: %s", - pseudonym, patientId, patientFirstName, patientLastName, issuerOfPatientId); - } + private Long projectID; + + public CachedPatient(String pseudonym, String patientId, String patientFirstName, String patientLastName, + String issuerOfPatientId, Long projectID) { + super(pseudonym, patientId, patientFirstName, patientLastName, null, null, issuerOfPatientId); + this.projectID = projectID; + } + + public void setPseudonym(String pseudonym) { + this.pseudonym = pseudonym; + } + + public void setPatientId(String patientId) { + this.patientId = patientId; + } + + public void setPatientFirstName(String patientFirstName) { + updatePatientFirstName(patientFirstName); + } + + public void setPatientLastName(String patientLastName) { + updatePatientLastName(patientLastName); + } + + public void setIssuerOfPatientId(String issuerOfPatientId) { + this.issuerOfPatientId = issuerOfPatientId; + } + + public Long getProjectID() { + return projectID; + } + + public void setProjectID(Long projectID) { + this.projectID = projectID; + } + + @Override + public String toString() { + return String.format( + "External pseudonym: %s, Patient ID: %s, Patient first name: %s, Patient last name: %s," + + " Issuer of patient ID: %s", + pseudonym, patientId, patientFirstName, patientLastName, issuerOfPatientId); + } + } diff --git a/src/main/java/org/karnak/backend/cache/ExternalIDCache.java b/src/main/java/org/karnak/backend/cache/ExternalIDCache.java index 7bd313c3b..2f304493e 100644 --- a/src/main/java/org/karnak/backend/cache/ExternalIDCache.java +++ b/src/main/java/org/karnak/backend/cache/ExternalIDCache.java @@ -14,10 +14,12 @@ @Component public class ExternalIDCache extends PatientClient { - private static final String NAME = "externalid"; - private static final int TTL_SECONDS = 60 * 60 * 24 * 7; + private static final String NAME = "externalid"; + + private static final int TTL_SECONDS = 60 * 60 * 24 * 7; + + public ExternalIDCache() { + super(NAME, TTL_SECONDS); + } - public ExternalIDCache() { - super(NAME, TTL_SECONDS); - } } diff --git a/src/main/java/org/karnak/backend/cache/MainzellisteCache.java b/src/main/java/org/karnak/backend/cache/MainzellisteCache.java index 120f2791d..58d2567f2 100644 --- a/src/main/java/org/karnak/backend/cache/MainzellisteCache.java +++ b/src/main/java/org/karnak/backend/cache/MainzellisteCache.java @@ -14,10 +14,12 @@ @Component public class MainzellisteCache extends PatientClient { - private static final String NAME = "mainzelliste"; - private static final int TTL_SECONDS = 15 * 60; + private static final String NAME = "mainzelliste"; + + private static final int TTL_SECONDS = 15 * 60; + + public MainzellisteCache() { + super(NAME, TTL_SECONDS); + } - public MainzellisteCache() { - super(NAME, TTL_SECONDS); - } } diff --git a/src/main/java/org/karnak/backend/cache/MainzellistePatient.java b/src/main/java/org/karnak/backend/cache/MainzellistePatient.java index fab48da9c..fa7713dbc 100644 --- a/src/main/java/org/karnak/backend/cache/MainzellistePatient.java +++ b/src/main/java/org/karnak/backend/cache/MainzellistePatient.java @@ -13,49 +13,37 @@ public class MainzellistePatient extends Patient { - public MainzellistePatient( - String pseudonym, - String patientId, - String patientFirstName, - String patientLastName, - LocalDate patientBirthDate, - String patientSex, - String issuerOfPatientId) { - super( - pseudonym, - patientId, - patientFirstName, - patientLastName, - patientBirthDate, - patientSex, - issuerOfPatientId); - } - - public void setPseudonym(String pseudonym) { - this.pseudonym = pseudonym; - } - - public void setPatientId(String patientId) { - this.patientId = patientId; - } - - public void setPatientFirstName(String patientFirstName) { - updatePatientFirstName(patientFirstName); - } - - public void setPatientLastName(String patientLastName) { - updatePatientLastName(patientLastName); - } - - public void setPatientBirthDate(LocalDate patientBirthDate) { - this.patientBirthDate = patientBirthDate; - } - - public void setPatientSex(String patientSex) { - this.patientSex = patientSex; - } - - public void setIssuerOfPatientId(String issuerOfPatientId) { - this.issuerOfPatientId = issuerOfPatientId; - } + public MainzellistePatient(String pseudonym, String patientId, String patientFirstName, String patientLastName, + LocalDate patientBirthDate, String patientSex, String issuerOfPatientId) { + super(pseudonym, patientId, patientFirstName, patientLastName, patientBirthDate, patientSex, issuerOfPatientId); + } + + public void setPseudonym(String pseudonym) { + this.pseudonym = pseudonym; + } + + public void setPatientId(String patientId) { + this.patientId = patientId; + } + + public void setPatientFirstName(String patientFirstName) { + updatePatientFirstName(patientFirstName); + } + + public void setPatientLastName(String patientLastName) { + updatePatientLastName(patientLastName); + } + + public void setPatientBirthDate(LocalDate patientBirthDate) { + this.patientBirthDate = patientBirthDate; + } + + public void setPatientSex(String patientSex) { + this.patientSex = patientSex; + } + + public void setIssuerOfPatientId(String issuerOfPatientId) { + this.issuerOfPatientId = issuerOfPatientId; + } + } diff --git a/src/main/java/org/karnak/backend/cache/Patient.java b/src/main/java/org/karnak/backend/cache/Patient.java index a2e2caf79..12a265d7f 100644 --- a/src/main/java/org/karnak/backend/cache/Patient.java +++ b/src/main/java/org/karnak/backend/cache/Patient.java @@ -14,128 +14,124 @@ public abstract class Patient implements PseudonymPatient, Serializable { - private static final Character SPLIT_CHAR_PATIENT_NAME = '^'; - protected String pseudonym; - protected String patientId; - protected String patientName; - protected String patientFirstName; - protected String patientLastName; - protected LocalDate patientBirthDate; - protected String patientSex; - protected String issuerOfPatientId; - - protected Patient( - String pseudonym, - String patientId, - String patientName, - LocalDate patientBirthDate, - String patientSex, - String issuerOfPatientId) { - this.pseudonym = pseudonym; - this.patientId = patientId; - this.patientName = patientName; - this.patientFirstName = createPatientFirstName(patientName); - this.patientLastName = createPatientLastName(patientName); - this.patientBirthDate = patientBirthDate; - this.patientSex = patientSex; - this.issuerOfPatientId = issuerOfPatientId; - } - - protected Patient( - String pseudonym, - String patientId, - String patientFirstName, - String patientLastName, - LocalDate patientBirthDate, - String patientSex, - String issuerOfPatientId) { - this.pseudonym = pseudonym; - this.patientId = patientId; - this.patientName = createPatientName(patientFirstName, patientLastName); - this.patientFirstName = emptyStringIfNull(patientFirstName); - this.patientLastName = emptyStringIfNull(patientLastName); - this.patientBirthDate = patientBirthDate; - this.patientSex = patientSex; - this.issuerOfPatientId = issuerOfPatientId; - } - - protected static String createPatientLastName(String patientName) { - return patientName.split(String.format("\\%c", SPLIT_CHAR_PATIENT_NAME))[0]; - } - - protected static String createPatientFirstName(String patientName) { - String[] patientNameSplitted = - patientName.split(String.format("\\%c", SPLIT_CHAR_PATIENT_NAME)); - if (patientNameSplitted.length > 1) { - return patientNameSplitted[1]; - } - return ""; - } - - protected static String createPatientName(String patientFirstName, String patientLastName) { - if (patientFirstName == null || patientFirstName.equals("")) { - return patientLastName; - } - return String.format( - "%s%c%s", - patientLastName == null ? "" : patientLastName, SPLIT_CHAR_PATIENT_NAME, patientFirstName); - } - - private static String emptyStringIfNull(String value) { - return value == null ? "" : value; - } - - public void updatePatientName(String patientName) { - this.patientName = patientName; - this.patientFirstName = createPatientFirstName(patientName); - this.patientLastName = createPatientLastName(patientName); - } - - protected void updatePatientLastName(String patientLastName) { - this.patientLastName = emptyStringIfNull(patientLastName); - this.patientName = createPatientName(patientFirstName, patientLastName); - } - - protected void updatePatientFirstName(String patientFirstName) { - this.patientFirstName = emptyStringIfNull(patientFirstName); - this.patientName = createPatientName(patientFirstName, patientLastName); - } - - @Override - public String getPseudonym() { - return pseudonym; - } - - @Override - public String getPatientId() { - return patientId; - } - - @Override - public String getPatientName() { - return patientName; - } - - public String getPatientFirstName() { - return patientFirstName; - } - - public String getPatientLastName() { - return patientLastName; - } - - @Override - public LocalDate getPatientBirthDate() { - return patientBirthDate; - } - - @Override - public String getPatientSex() { - return patientSex; - } - - @Override - public String getIssuerOfPatientId() { - return issuerOfPatientId; - } + private static final Character SPLIT_CHAR_PATIENT_NAME = '^'; + + protected String pseudonym; + + protected String patientId; + + protected String patientName; + + protected String patientFirstName; + + protected String patientLastName; + + protected LocalDate patientBirthDate; + + protected String patientSex; + + protected String issuerOfPatientId; + + protected Patient(String pseudonym, String patientId, String patientName, LocalDate patientBirthDate, + String patientSex, String issuerOfPatientId) { + this.pseudonym = pseudonym; + this.patientId = patientId; + this.patientName = patientName; + this.patientFirstName = createPatientFirstName(patientName); + this.patientLastName = createPatientLastName(patientName); + this.patientBirthDate = patientBirthDate; + this.patientSex = patientSex; + this.issuerOfPatientId = issuerOfPatientId; + } + + protected Patient(String pseudonym, String patientId, String patientFirstName, String patientLastName, + LocalDate patientBirthDate, String patientSex, String issuerOfPatientId) { + this.pseudonym = pseudonym; + this.patientId = patientId; + this.patientName = createPatientName(patientFirstName, patientLastName); + this.patientFirstName = emptyStringIfNull(patientFirstName); + this.patientLastName = emptyStringIfNull(patientLastName); + this.patientBirthDate = patientBirthDate; + this.patientSex = patientSex; + this.issuerOfPatientId = issuerOfPatientId; + } + + protected static String createPatientLastName(String patientName) { + return patientName.split(String.format("\\%c", SPLIT_CHAR_PATIENT_NAME))[0]; + } + + protected static String createPatientFirstName(String patientName) { + String[] patientNameSplitted = patientName.split(String.format("\\%c", SPLIT_CHAR_PATIENT_NAME)); + if (patientNameSplitted.length > 1) { + return patientNameSplitted[1]; + } + return ""; + } + + protected static String createPatientName(String patientFirstName, String patientLastName) { + if (patientFirstName == null || patientFirstName.equals("")) { + return patientLastName; + } + return String.format("%s%c%s", patientLastName == null ? "" : patientLastName, SPLIT_CHAR_PATIENT_NAME, + patientFirstName); + } + + private static String emptyStringIfNull(String value) { + return value == null ? "" : value; + } + + public void updatePatientName(String patientName) { + this.patientName = patientName; + this.patientFirstName = createPatientFirstName(patientName); + this.patientLastName = createPatientLastName(patientName); + } + + protected void updatePatientLastName(String patientLastName) { + this.patientLastName = emptyStringIfNull(patientLastName); + this.patientName = createPatientName(patientFirstName, patientLastName); + } + + protected void updatePatientFirstName(String patientFirstName) { + this.patientFirstName = emptyStringIfNull(patientFirstName); + this.patientName = createPatientName(patientFirstName, patientLastName); + } + + @Override + public String getPseudonym() { + return pseudonym; + } + + @Override + public String getPatientId() { + return patientId; + } + + @Override + public String getPatientName() { + return patientName; + } + + public String getPatientFirstName() { + return patientFirstName; + } + + public String getPatientLastName() { + return patientLastName; + } + + @Override + public LocalDate getPatientBirthDate() { + return patientBirthDate; + } + + @Override + public String getPatientSex() { + return patientSex; + } + + @Override + public String getIssuerOfPatientId() { + return issuerOfPatientId; + } + } diff --git a/src/main/java/org/karnak/backend/cache/PatientClient.java b/src/main/java/org/karnak/backend/cache/PatientClient.java index 6c0dfbd8e..daa78f479 100644 --- a/src/main/java/org/karnak/backend/cache/PatientClient.java +++ b/src/main/java/org/karnak/backend/cache/PatientClient.java @@ -18,48 +18,53 @@ public abstract class PatientClient { - // https://docs.hazelcast.org/docs/latest/manual/html-single/#cp-subsystem - private static final String CLUSTER_NAME = "PatientClient"; - private static final int CP_MEMBER = 3; - private final String name; - private final HazelcastInstance hazelcastInstance; + // https://docs.hazelcast.org/docs/latest/manual/html-single/#cp-subsystem + private static final String CLUSTER_NAME = "PatientClient"; - public PatientClient(String name, int ttlSeconds) { - this.name = name; - this.hazelcastInstance = Hazelcast.newHazelcastInstance(createConfig(ttlSeconds)); - } + private static final int CP_MEMBER = 3; - private Config createConfig(int ttlSeconds) { - Config config = new Config(); - MapConfig mapConfig = new MapConfig(name); - mapConfig.setTimeToLiveSeconds(ttlSeconds); - // The method setMaxIdleSeconds defines how long the entry stays in the cache without being - // touched - // mapConfig.setMaxIdleSeconds(20); - config.addMapConfig(mapConfig); - config.setClusterName(CLUSTER_NAME); - config.getCPSubsystemConfig().setCPMemberCount(CP_MEMBER); - config.setClassLoader(PseudonymPatient.class.getClassLoader()); - return config; - } + private final String name; - public PseudonymPatient put(String key, PseudonymPatient patient) { - IMap map = hazelcastInstance.getMap(name); - return map.putIfAbsent(key, patient); - } + private final HazelcastInstance hazelcastInstance; - public PseudonymPatient get(String key) { - IMap map = hazelcastInstance.getMap(name); - return map.get(key); - } + public PatientClient(String name, int ttlSeconds) { + this.name = name; + this.hazelcastInstance = Hazelcast.newHazelcastInstance(createConfig(ttlSeconds)); + } - public void remove(String key) { - IMap map = hazelcastInstance.getMap(name); - map.remove(key); - } + private Config createConfig(int ttlSeconds) { + Config config = new Config(); + MapConfig mapConfig = new MapConfig(name); + mapConfig.setTimeToLiveSeconds(ttlSeconds); + // The method setMaxIdleSeconds defines how long the entry stays in the cache + // without being + // touched + // mapConfig.setMaxIdleSeconds(20); + config.addMapConfig(mapConfig); + config.setClusterName(CLUSTER_NAME); + config.getCPSubsystemConfig().setCPMemberCount(CP_MEMBER); + config.setClassLoader(PseudonymPatient.class.getClassLoader()); + return config; + } + + public PseudonymPatient put(String key, PseudonymPatient patient) { + IMap map = hazelcastInstance.getMap(name); + return map.putIfAbsent(key, patient); + } + + public PseudonymPatient get(String key) { + IMap map = hazelcastInstance.getMap(name); + return map.get(key); + } + + public void remove(String key) { + IMap map = hazelcastInstance.getMap(name); + map.remove(key); + } + + public Collection getAll() { + IMap map = hazelcastInstance.getMap(name); + return map.values(); + } - public Collection getAll() { - IMap map = hazelcastInstance.getMap(name); - return map.values(); - } } diff --git a/src/main/java/org/karnak/backend/cache/PseudonymPatient.java b/src/main/java/org/karnak/backend/cache/PseudonymPatient.java index 2cd1bacb7..baa98d5b3 100644 --- a/src/main/java/org/karnak/backend/cache/PseudonymPatient.java +++ b/src/main/java/org/karnak/backend/cache/PseudonymPatient.java @@ -12,15 +12,17 @@ import java.time.LocalDate; public interface PseudonymPatient { - String getPseudonym(); - String getPatientId(); + String getPseudonym(); - String getPatientName(); + String getPatientId(); - String getIssuerOfPatientId(); + String getPatientName(); - LocalDate getPatientBirthDate(); + String getIssuerOfPatientId(); + + LocalDate getPatientBirthDate(); + + String getPatientSex(); - String getPatientSex(); } diff --git a/src/main/java/org/karnak/backend/cache/RequestCache.java b/src/main/java/org/karnak/backend/cache/RequestCache.java index 5fce1abad..2fc212f65 100644 --- a/src/main/java/org/karnak/backend/cache/RequestCache.java +++ b/src/main/java/org/karnak/backend/cache/RequestCache.java @@ -20,40 +20,37 @@ public class RequestCache extends HttpSessionRequestCache { - /** - * Saves unauthenticated requests so we can redirect the user to the page they were trying to - * access once they’re logged in - * - * @param request Request - * @param response Response - */ - @Override - public void saveRequest(HttpServletRequest request, HttpServletResponse response) { - if (!SecurityUtil.isFrameworkInternalRequest(request)) { - super.saveRequest(request, response); - } - } + /** + * Saves unauthenticated requests so we can redirect the user to the page they were + * trying to access once they’re logged in + * @param request Request + * @param response Response + */ + @Override + public void saveRequest(HttpServletRequest request, HttpServletResponse response) { + if (!SecurityUtil.isFrameworkInternalRequest(request)) { + super.saveRequest(request, response); + } + } - /** - * Determine the path to navigate to: Retrieve if existing the saved request or redirect to the - * root path - * - * @return the path resolved - */ - public String resolveRedirectUrl() { - SavedRequest savedRequest = - getRequest( - VaadinServletRequest.getCurrent().getHttpServletRequest(), - VaadinServletResponse.getCurrent().getHttpServletResponse()); - if (savedRequest instanceof DefaultSavedRequest) { - final String requestURI = ((DefaultSavedRequest) savedRequest).getRequestURI(); - // check for valid URI - if (requestURI != null && !requestURI.isEmpty()) { - return requestURI.startsWith("/") ? requestURI.substring(1) : requestURI; - } - } + /** + * Determine the path to navigate to: Retrieve if existing the saved request or + * redirect to the root path + * @return the path resolved + */ + public String resolveRedirectUrl() { + SavedRequest savedRequest = getRequest(VaadinServletRequest.getCurrent().getHttpServletRequest(), + VaadinServletResponse.getCurrent().getHttpServletResponse()); + if (savedRequest instanceof DefaultSavedRequest) { + final String requestURI = ((DefaultSavedRequest) savedRequest).getRequestURI(); + // check for valid URI + if (requestURI != null && !requestURI.isEmpty()) { + return requestURI.startsWith("/") ? requestURI.substring(1) : requestURI; + } + } + + // if everything fails, redirect to the main view + return ""; + } - // if everything fails, redirect to the main view - return ""; - } } diff --git a/src/main/java/org/karnak/backend/config/AppConfig.java b/src/main/java/org/karnak/backend/config/AppConfig.java index 8ddf9abb6..f94ec9c83 100644 --- a/src/main/java/org/karnak/backend/config/AppConfig.java +++ b/src/main/java/org/karnak/backend/config/AppConfig.java @@ -39,101 +39,110 @@ @ConfigurationProperties public class AppConfig { - private static final Logger LOGGER = LoggerFactory.getLogger(AppConfig.class); - - private static AppConfig instance; - private String environment; - private String name; - private String karnakadmin; - private String karnakpassword; - private final ProfileRepo profileRepo; - private final ProfilePipeService profilePipeService; - private String nameInstance; - - @Autowired - public AppConfig(final ProfileRepo profileRepo, final ProfilePipeService profilePipeService) { - this.profileRepo = profileRepo; - this.profilePipeService = profilePipeService; - } - - @PostConstruct - public void postConstruct() { - instance = this; - nameInstance = RandomStringUtils.randomAlphabetic(5); - } - - public static AppConfig getInstance() { - return instance; - } - - public String getEnvironment() { - return environment; - } - - public void setEnvironment(String environment) { - this.environment = environment; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getKarnakadmin() { - return karnakadmin != null ? karnakadmin : "admin"; - } - - public void setKarnakadmin(String karnakadmin) { - this.karnakadmin = karnakadmin; - } - - public String getKarnakpassword() { - return karnakpassword != null ? karnakpassword : "admin"; - } - - public void setKarnakpassword(String karnakpassword) { - this.karnakpassword = karnakpassword; - } - - @Bean("ConfidentialityProfiles") - public ConfidentialityProfiles getConfidentialityProfile() { - return new ConfidentialityProfiles(); - } - - @Bean("ExternalIDPatient") - public PatientClient getExternalIDCache() { - return new ExternalIDCache(); - } - - @Bean("MainzellisteCache") - public PatientClient getMainzellisteCache() { - return new MainzellisteCache(); - } - - // https://stackoverflow.com/questions/27405713/running-code-after-spring-boot-starts - @EventListener(ApplicationReadyEvent.class) - public void setProfilesByDefault() { - URL profileURL = Profile.class.getResource("profileByDefault.yml"); - if (!profileRepo.existsByNameAndByDefault("Dicom Basic Profile", true)) { - try (InputStream inputStream = profileURL.openStream()) { - final Yaml yaml = new Yaml(new Constructor(ProfilePipeBody.class)); - final ProfilePipeBody profilePipeYml = yaml.load(inputStream); - profilePipeService.saveProfilePipe(profilePipeYml, true); - } catch (final Exception e) { - LOGGER.error("Cannot persist default profile {}", profileURL, e); - } - } - } - - @Bean("StandardDICOM") - public StandardDICOM getStandardDICOM() { - return new StandardDICOM(); - } - - public String getNameInstance() { - return nameInstance; - } + private static final Logger LOGGER = LoggerFactory.getLogger(AppConfig.class); + + private static AppConfig instance; + + private String environment; + + private String name; + + private String karnakadmin; + + private String karnakpassword; + + private final ProfileRepo profileRepo; + + private final ProfilePipeService profilePipeService; + + private String nameInstance; + + @Autowired + public AppConfig(final ProfileRepo profileRepo, final ProfilePipeService profilePipeService) { + this.profileRepo = profileRepo; + this.profilePipeService = profilePipeService; + } + + @PostConstruct + public void postConstruct() { + instance = this; + nameInstance = RandomStringUtils.randomAlphabetic(5); + } + + public static AppConfig getInstance() { + return instance; + } + + public String getEnvironment() { + return environment; + } + + public void setEnvironment(String environment) { + this.environment = environment; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getKarnakadmin() { + return karnakadmin != null ? karnakadmin : "admin"; + } + + public void setKarnakadmin(String karnakadmin) { + this.karnakadmin = karnakadmin; + } + + public String getKarnakpassword() { + return karnakpassword != null ? karnakpassword : "admin"; + } + + public void setKarnakpassword(String karnakpassword) { + this.karnakpassword = karnakpassword; + } + + @Bean("ConfidentialityProfiles") + public ConfidentialityProfiles getConfidentialityProfile() { + return new ConfidentialityProfiles(); + } + + @Bean("ExternalIDPatient") + public PatientClient getExternalIDCache() { + return new ExternalIDCache(); + } + + @Bean("MainzellisteCache") + public PatientClient getMainzellisteCache() { + return new MainzellisteCache(); + } + + // https://stackoverflow.com/questions/27405713/running-code-after-spring-boot-starts + @EventListener(ApplicationReadyEvent.class) + public void setProfilesByDefault() { + URL profileURL = Profile.class.getResource("profileByDefault.yml"); + if (!profileRepo.existsByNameAndByDefault("Dicom Basic Profile", true)) { + try (InputStream inputStream = profileURL.openStream()) { + final Yaml yaml = new Yaml(new Constructor(ProfilePipeBody.class)); + final ProfilePipeBody profilePipeYml = yaml.load(inputStream); + profilePipeService.saveProfilePipe(profilePipeYml, true); + } + catch (final Exception e) { + LOGGER.error("Cannot persist default profile {}", profileURL, e); + } + } + } + + @Bean("StandardDICOM") + public StandardDICOM getStandardDICOM() { + return new StandardDICOM(); + } + + public String getNameInstance() { + return nameInstance; + } + } diff --git a/src/main/java/org/karnak/backend/config/DcmProfileConfig.java b/src/main/java/org/karnak/backend/config/DcmProfileConfig.java index 735306864..59f19d245 100644 --- a/src/main/java/org/karnak/backend/config/DcmProfileConfig.java +++ b/src/main/java/org/karnak/backend/config/DcmProfileConfig.java @@ -19,18 +19,19 @@ @ConfigurationProperties(prefix = "dcmprofile") public class DcmProfileConfig { - private static DcmProfileConfig instance; + private static DcmProfileConfig instance; - public static DcmProfileConfig getInstance() { - return instance; - } + public static DcmProfileConfig getInstance() { + return instance; + } - public static void setInstance(DcmProfileConfig instance) { - DcmProfileConfig.instance = instance; - } + public static void setInstance(DcmProfileConfig instance) { + DcmProfileConfig.instance = instance; + } + + @PostConstruct + public void postConstruct() { + instance = this; + } - @PostConstruct - public void postConstruct() { - instance = this; - } } diff --git a/src/main/java/org/karnak/backend/config/EmailConfig.java b/src/main/java/org/karnak/backend/config/EmailConfig.java index 973860da1..707f04f7e 100644 --- a/src/main/java/org/karnak/backend/config/EmailConfig.java +++ b/src/main/java/org/karnak/backend/config/EmailConfig.java @@ -21,38 +21,41 @@ @Configuration public class EmailConfig { - @Bean - public JavaMailSender getJavaMailSender() { - - // retrieve system properties - String mailSmtpPort = SystemPropertyUtil.retrieveSystemProperty("MAIL_SMTP_PORT", "0"); - String mailSmtpUser = SystemPropertyUtil.retrieveSystemProperty("MAIL_SMTP_USER", null); - String mailAuthType = SystemPropertyUtil.retrieveSystemProperty("MAIL_SMTP_TYPE", null); - - // Configure JavaMailSender - JavaMailSenderImpl mailSender = new JavaMailSenderImpl(); - mailSender.setHost(SystemPropertyUtil.retrieveSystemProperty("MAIL_SMTP_HOST", null)); - mailSender.setPort(Integer.parseInt(mailSmtpPort)); - mailSender.setUsername(mailSmtpUser); - mailSender.setPassword(SystemPropertyUtil.retrieveSystemProperty("MAIL_SMTP_SECRET", null)); - - // Additional properties - Properties props = mailSender.getJavaMailProperties(); - props.put("mail.transport.protocol", "smtp"); - - // Value with authentication should be "SSL" or "STARTTLS" - if (StringUtil.hasText(mailAuthType)) { - props.put("mail.smtp.auth", "true"); - if (Objects.equals("SSL", mailAuthType)) { - props.put("mail.smtp.socketFactory.port", mailSmtpPort); // SSL Port - props.put( - "mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); // SSL Factory Class - props.put("mail.smtp.ssl.checkserveridentity", true); - } else { - props.put("mail.smtp.starttls.enable", "true"); - } - props.setProperty("mail.smtp.submitter", mailSmtpUser); - } - return mailSender; - } + @Bean + public JavaMailSender getJavaMailSender() { + + // retrieve system properties + String mailSmtpPort = SystemPropertyUtil.retrieveSystemProperty("MAIL_SMTP_PORT", "0"); + String mailSmtpUser = SystemPropertyUtil.retrieveSystemProperty("MAIL_SMTP_USER", null); + String mailAuthType = SystemPropertyUtil.retrieveSystemProperty("MAIL_SMTP_TYPE", null); + + // Configure JavaMailSender + JavaMailSenderImpl mailSender = new JavaMailSenderImpl(); + mailSender.setHost(SystemPropertyUtil.retrieveSystemProperty("MAIL_SMTP_HOST", null)); + mailSender.setPort(Integer.parseInt(mailSmtpPort)); + mailSender.setUsername(mailSmtpUser); + mailSender.setPassword(SystemPropertyUtil.retrieveSystemProperty("MAIL_SMTP_SECRET", null)); + + // Additional properties + Properties props = mailSender.getJavaMailProperties(); + props.put("mail.transport.protocol", "smtp"); + + // Value with authentication should be "SSL" or "STARTTLS" + if (StringUtil.hasText(mailAuthType)) { + props.put("mail.smtp.auth", "true"); + if (Objects.equals("SSL", mailAuthType)) { + props.put("mail.smtp.socketFactory.port", mailSmtpPort); // SSL Port + props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); // SSL + // Factory + // Class + props.put("mail.smtp.ssl.checkserveridentity", true); + } + else { + props.put("mail.smtp.starttls.enable", "true"); + } + props.setProperty("mail.smtp.submitter", mailSmtpUser); + } + return mailSender; + } + } diff --git a/src/main/java/org/karnak/backend/config/GatewayConfig.java b/src/main/java/org/karnak/backend/config/GatewayConfig.java index bf08179c8..f11e9f856 100644 --- a/src/main/java/org/karnak/backend/config/GatewayConfig.java +++ b/src/main/java/org/karnak/backend/config/GatewayConfig.java @@ -24,26 +24,27 @@ @EnableJpaRepositories public class GatewayConfig { - // Repositories - private final SOPClassUIDRepo sopClassUIDRepo; + // Repositories + private final SOPClassUIDRepo sopClassUIDRepo; - @Autowired - public GatewayConfig(final SOPClassUIDRepo sopClassUIDRepo) { - this.sopClassUIDRepo = sopClassUIDRepo; - } + @Autowired + public GatewayConfig(final SOPClassUIDRepo sopClassUIDRepo) { + this.sopClassUIDRepo = sopClassUIDRepo; + } + + @PostConstruct + private void writeSOPSinDatabase() { + final StandardSOPS standardSOPS = new StandardSOPS(); + Set sopClassUIDEntitySet = new HashSet<>(); + for (jsonSOP sop : standardSOPS.getSOPS()) { + final String ciod = sop.getCiod(); + final String uid = sop.getId(); + final String name = sop.getName(); + if (sopClassUIDRepo.existsByCiodAndUidAndName(ciod, uid, name).equals(Boolean.FALSE)) { + sopClassUIDEntitySet.add(new SOPClassUIDEntity(ciod, uid, name)); + } + } + sopClassUIDRepo.saveAll(sopClassUIDEntitySet); + } - @PostConstruct - private void writeSOPSinDatabase() { - final StandardSOPS standardSOPS = new StandardSOPS(); - Set sopClassUIDEntitySet = new HashSet<>(); - for (jsonSOP sop : standardSOPS.getSOPS()) { - final String ciod = sop.getCiod(); - final String uid = sop.getId(); - final String name = sop.getName(); - if (sopClassUIDRepo.existsByCiodAndUidAndName(ciod, uid, name).equals(Boolean.FALSE)) { - sopClassUIDEntitySet.add(new SOPClassUIDEntity(ciod, uid, name)); - } - } - sopClassUIDRepo.saveAll(sopClassUIDEntitySet); - } } diff --git a/src/main/java/org/karnak/backend/config/HazelcastConfig.java b/src/main/java/org/karnak/backend/config/HazelcastConfig.java index f35de91e4..0baa7e8df 100644 --- a/src/main/java/org/karnak/backend/config/HazelcastConfig.java +++ b/src/main/java/org/karnak/backend/config/HazelcastConfig.java @@ -17,18 +17,14 @@ @Configuration public class HazelcastConfig { - @Bean - @Profile("!test") - public Config hazelcastConfiguration() { - Config config = new Config(); - config.getNetworkConfig().getJoin().getMulticastConfig().setEnabled(false); - config - .getNetworkConfig() - .getJoin() - .getEurekaConfig() - .setEnabled(true) - .setProperty("self-registration", "true") - .setProperty("namespace", "hazelcast"); - return config; - } + @Bean + @Profile("!test") + public Config hazelcastConfiguration() { + Config config = new Config(); + config.getNetworkConfig().getJoin().getMulticastConfig().setEnabled(false); + config.getNetworkConfig().getJoin().getEurekaConfig().setEnabled(true).setProperty("self-registration", "true") + .setProperty("namespace", "hazelcast"); + return config; + } + } diff --git a/src/main/java/org/karnak/backend/config/MainzellisteConfig.java b/src/main/java/org/karnak/backend/config/MainzellisteConfig.java index 298c0cda6..32ee8c6a7 100644 --- a/src/main/java/org/karnak/backend/config/MainzellisteConfig.java +++ b/src/main/java/org/karnak/backend/config/MainzellisteConfig.java @@ -19,41 +19,45 @@ @ConfigurationProperties(prefix = "mainzelliste") public class MainzellisteConfig { - private static MainzellisteConfig instance; - private String apikey; - private String serverurl; - private String idtypes; - - public static MainzellisteConfig getInstance() { - return instance; - } - - @PostConstruct - public void postConstruct() { - instance = this; - } - - public String getApikey() { - return apikey; - } - - public void setApikey(String apikey) { - this.apikey = apikey; - } - - public String getServerurl() { - return serverurl; - } - - public void setServerurl(String serverurl) { - this.serverurl = serverurl; - } - - public String getIdtypes() { - return idtypes; - } - - public void setIdtypes(String idtypes) { - this.idtypes = idtypes; - } + private static MainzellisteConfig instance; + + private String apikey; + + private String serverurl; + + private String idtypes; + + public static MainzellisteConfig getInstance() { + return instance; + } + + @PostConstruct + public void postConstruct() { + instance = this; + } + + public String getApikey() { + return apikey; + } + + public void setApikey(String apikey) { + this.apikey = apikey; + } + + public String getServerurl() { + return serverurl; + } + + public void setServerurl(String serverurl) { + this.serverurl = serverurl; + } + + public String getIdtypes() { + return idtypes; + } + + public void setIdtypes(String idtypes) { + this.idtypes = idtypes; + } + } diff --git a/src/main/java/org/karnak/backend/config/SecurityInMemoryConfig.java b/src/main/java/org/karnak/backend/config/SecurityInMemoryConfig.java index 5d0b7627c..9ef8c4022 100644 --- a/src/main/java/org/karnak/backend/config/SecurityInMemoryConfig.java +++ b/src/main/java/org/karnak/backend/config/SecurityInMemoryConfig.java @@ -29,90 +29,67 @@ @Conditional(value = DefaultIdpLoadCondition.class) public class SecurityInMemoryConfig extends WebSecurityConfigurerAdapter { - private static final String LOGIN_FAILURE_URL = "/login?error"; - private static final String LOGIN_URL = "/login"; + private static final String LOGIN_FAILURE_URL = "/login?error"; - @Override - protected void configure(HttpSecurity http) throws Exception { + private static final String LOGIN_URL = "/login"; - http - // Uses RequestCache to track unauthorized requests so that users are redirected - // appropriately after login - .requestCache() - .requestCache(new RequestCache()) - // Disables cross-site request forgery (CSRF) protection for main route and login - .and() - .csrf() - .ignoringAntMatchers("/", LOGIN_URL) - // Turns on authorization - .and() - .authorizeRequests() - // Allows all internal traffic from the Vaadin framework - .requestMatchers(SecurityUtil::isFrameworkInternalRequest) - .permitAll() - // Allow get echo endpoint - .antMatchers(HttpMethod.GET, "/api/echo/destinations") - .permitAll() - // Allows all authenticated traffic - .antMatchers("/*") - .hasRole(SecurityRole.ADMIN_ROLE.getType()) - .anyRequest() - .authenticated() - // Enables form-based login and permits unauthenticated access to it - .and() - .formLogin() - // Configures the login page URLs - .loginPage(LOGIN_URL) - .permitAll() - .loginProcessingUrl(LOGIN_URL) - .failureUrl(LOGIN_FAILURE_URL) - // Configures the logout URL - .and() - .logout() - .logoutSuccessUrl(LOGIN_URL) - .and() - .exceptionHandling() - .accessDeniedPage(LOGIN_URL); - } + @Override + protected void configure(HttpSecurity http) throws Exception { - @Override - protected void configure(AuthenticationManagerBuilder auth) throws Exception { - // Configure users and roles in memory - auth.inMemoryAuthentication() - .withUser(AppConfig.getInstance().getKarnakadmin()) - .password("{noop}" + AppConfig.getInstance().getKarnakpassword()) - .roles( - SecurityRole.ADMIN_ROLE.getType(), - SecurityRole.INVESTIGATOR_ROLE.getType(), - SecurityRole.USER_ROLE.getType()); - } + http + // Uses RequestCache to track unauthorized requests so that users are + // redirected + // appropriately after login + .requestCache().requestCache(new RequestCache()) + // Disables cross-site request forgery (CSRF) protection for main route + // and login + .and().csrf().ignoringAntMatchers("/", LOGIN_URL) + // Turns on authorization + .and().authorizeRequests() + // Allows all internal traffic from the Vaadin framework + .requestMatchers(SecurityUtil::isFrameworkInternalRequest).permitAll() + // Allow get echo endpoint + .antMatchers(HttpMethod.GET, "/api/echo/destinations").permitAll() + // Allows all authenticated traffic + .antMatchers("/*").hasRole(SecurityRole.ADMIN_ROLE.getType()).anyRequest().authenticated() + // Enables form-based login and permits unauthenticated access to it + .and().formLogin() + // Configures the login page URLs + .loginPage(LOGIN_URL).permitAll().loginProcessingUrl(LOGIN_URL).failureUrl(LOGIN_FAILURE_URL) + // Configures the logout URL + .and().logout().logoutSuccessUrl(LOGIN_URL).and().exceptionHandling().accessDeniedPage(LOGIN_URL); + } - @Override - public void configure(WebSecurity web) { - // Access to static resources, bypassing Spring security. - web.ignoring() - .antMatchers( - "/VAADIN/**", - // the standard favicon URI - "/favicon.ico", - // web application manifest - "/manifest.webmanifest", - "/sw.js", - "/offline.html", - "/sw-runtime-resources-precache.js", - // icons and images - "/icons/logo**", - "/img/karnak.png"); - } + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // Configure users and roles in memory + auth.inMemoryAuthentication().withUser(AppConfig.getInstance().getKarnakadmin()) + .password("{noop}" + AppConfig.getInstance().getKarnakpassword()) + .roles(SecurityRole.ADMIN_ROLE.getType(), SecurityRole.INVESTIGATOR_ROLE.getType(), + SecurityRole.USER_ROLE.getType()); + } - @Bean - @Override - public AuthenticationManager authenticationManagerBean() throws Exception { - return super.authenticationManagerBean(); - } + @Override + public void configure(WebSecurity web) { + // Access to static resources, bypassing Spring security. + web.ignoring().antMatchers("/VAADIN/**", + // the standard favicon URI + "/favicon.ico", + // web application manifest + "/manifest.webmanifest", "/sw.js", "/offline.html", "/sw-runtime-resources-precache.js", + // icons and images + "/icons/logo**", "/img/karnak.png"); + } + + @Bean + @Override + public AuthenticationManager authenticationManagerBean() throws Exception { + return super.authenticationManagerBean(); + } + + @Bean + public RequestCache requestCache() { // + return new RequestCache(); + } - @Bean - public RequestCache requestCache() { // - return new RequestCache(); - } } diff --git a/src/main/java/org/karnak/backend/config/SecurityOpenIdConnectConfig.java b/src/main/java/org/karnak/backend/config/SecurityOpenIdConnectConfig.java index 49e98308e..e3bd7348e 100644 --- a/src/main/java/org/karnak/backend/config/SecurityOpenIdConnectConfig.java +++ b/src/main/java/org/karnak/backend/config/SecurityOpenIdConnectConfig.java @@ -40,112 +40,87 @@ @ConditionalOnProperty(value = "IDP", havingValue = "oidc") public class SecurityOpenIdConnectConfig extends WebSecurityConfigurerAdapter { - @Value("${spring.security.oauth2.client.provider.keycloak.jwk-set-uri}") - private String jwkSetUri; + @Value("${spring.security.oauth2.client.provider.keycloak.jwk-set-uri}") + private String jwkSetUri; - @Override - protected void configure(HttpSecurity http) throws Exception { - http - // Uses RequestCache to track unauthorized requests so that users are redirected - // appropriately after login - .requestCache() - .requestCache(new RequestCache()) - // Disables cross-site request forgery (CSRF) protection for main route - .and() - .csrf() - .ignoringAntMatchers("/") - // Turns on authorization - .and() - .authorizeRequests() - // Allows all internal traffic from the Vaadin framework - .requestMatchers(SecurityUtil::isFrameworkInternalRequest) - .permitAll() - // Allow get echo endpoint - .antMatchers(HttpMethod.GET, "/api/echo/destinations") - .permitAll() - // Allows all authenticated traffic - .anyRequest() - .authenticated() - // OpenId connect login - .and() - .oauth2Login( - oauth2Login -> - oauth2Login.userInfoEndpoint( - // Extract roles from access token - userInfoEndpoint -> userInfoEndpoint.oidcUserService(oidcUserService()))) - // Handle logout - .logout() - .addLogoutHandler(new OpenIdConnectLogoutHandler()); - } + @Override + protected void configure(HttpSecurity http) throws Exception { + http + // Uses RequestCache to track unauthorized requests so that users are + // redirected + // appropriately after login + .requestCache().requestCache(new RequestCache()) + // Disables cross-site request forgery (CSRF) protection for main route + .and().csrf().ignoringAntMatchers("/") + // Turns on authorization + .and().authorizeRequests() + // Allows all internal traffic from the Vaadin framework + .requestMatchers(SecurityUtil::isFrameworkInternalRequest).permitAll() + // Allow get echo endpoint + .antMatchers(HttpMethod.GET, "/api/echo/destinations").permitAll() + // Allows all authenticated traffic + .anyRequest().authenticated() + // OpenId connect login + .and().oauth2Login(oauth2Login -> oauth2Login.userInfoEndpoint( + // Extract roles from access token + userInfoEndpoint -> userInfoEndpoint.oidcUserService(oidcUserService()))) + // Handle logout + .logout().addLogoutHandler(new OpenIdConnectLogoutHandler()); + } - @Override - public void configure(WebSecurity web) { - // Access to static resources, bypassing Spring security. - web.ignoring() - .antMatchers( - "/VAADIN/**", - // the standard favicon URI - "/favicon.ico", - // web application manifest - "/manifest.webmanifest", - "/sw.js", - "/offline.html", - "/sw-runtime-resources-precache.js", - // icons and images - "/icons/logo**", - "/img/karnak.png"); - } + @Override + public void configure(WebSecurity web) { + // Access to static resources, bypassing Spring security. + web.ignoring().antMatchers("/VAADIN/**", + // the standard favicon URI + "/favicon.ico", + // web application manifest + "/manifest.webmanifest", "/sw.js", "/offline.html", "/sw-runtime-resources-precache.js", + // icons and images + "/icons/logo**", "/img/karnak.png"); + } - /** - * Retrieve roles from access token - * - * @param jwt access token - * @return Roles found - */ - private Set retrieveRolesFromAccessToken(Jwt jwt) { - // Build roles - return ((List) - ((Map) - ((Map) jwt.getClaims().get(Token.RESOURCE_ACCESS)) - .get(Token.RESOURCE_NAME)) - .get(Token.ROLES)) - .stream() - .map(roleName -> Token.PREFIX_ROLE + roleName) - .map(SimpleGrantedAuthority::new) - .collect(Collectors.toSet()); - } + /** + * Retrieve roles from access token + * @param jwt access token + * @return Roles found + */ + private Set retrieveRolesFromAccessToken(Jwt jwt) { + // Build roles + return ((List) ((Map) ((Map) jwt.getClaims().get(Token.RESOURCE_ACCESS)) + .get(Token.RESOURCE_NAME)).get(Token.ROLES)).stream().map(roleName -> Token.PREFIX_ROLE + roleName) + .map(SimpleGrantedAuthority::new).collect(Collectors.toSet()); + } - /** - * Decode access token - * - * @param accessToken Access token to decode - * @return access token decoded - */ - private Jwt decodeAccessToken(OAuth2AccessToken accessToken) { - return NimbusJwtDecoder.withJwkSetUri(jwkSetUri).build().decode(accessToken.getTokenValue()); - } + /** + * Decode access token + * @param accessToken Access token to decode + * @return access token decoded + */ + private Jwt decodeAccessToken(OAuth2AccessToken accessToken) { + return NimbusJwtDecoder.withJwkSetUri(jwkSetUri).build().decode(accessToken.getTokenValue()); + } - /** - * Extract roles from access token and set authorities in the authenticated user - * - * @return OAuth2UserService - */ - private OAuth2UserService oidcUserService() { - final OidcUserService oidcUserService = new OidcUserService(); - return userRequest -> { - // Get the user from the request - OidcUser oidcUser = oidcUserService.loadUser(userRequest); + /** + * Extract roles from access token and set authorities in the authenticated user + * @return OAuth2UserService + */ + private OAuth2UserService oidcUserService() { + final OidcUserService oidcUserService = new OidcUserService(); + return userRequest -> { + // Get the user from the request + OidcUser oidcUser = oidcUserService.loadUser(userRequest); - // Decode access token - Jwt jwt = decodeAccessToken(userRequest.getAccessToken()); + // Decode access token + Jwt jwt = decodeAccessToken(userRequest.getAccessToken()); - // Retrieve roles from access token - Set grantedAuthoritiesFromAccessToken = - retrieveRolesFromAccessToken(jwt); + // Retrieve roles from access token + Set grantedAuthoritiesFromAccessToken = retrieveRolesFromAccessToken(jwt); + + // Update the user with roles found + return new DefaultOidcUser(grantedAuthoritiesFromAccessToken, oidcUser.getIdToken(), + oidcUser.getUserInfo()); + }; + } - // Update the user with roles found - return new DefaultOidcUser( - grantedAuthoritiesFromAccessToken, oidcUser.getIdToken(), oidcUser.getUserInfo()); - }; - } } diff --git a/src/main/java/org/karnak/backend/config/WebConfig.java b/src/main/java/org/karnak/backend/config/WebConfig.java index 114198f80..ad1a12868 100644 --- a/src/main/java/org/karnak/backend/config/WebConfig.java +++ b/src/main/java/org/karnak/backend/config/WebConfig.java @@ -19,14 +19,11 @@ @EnableWebMvc public class WebConfig implements WebMvcConfigurer { - @Override - public void addResourceHandlers(ResourceHandlerRegistry registry) { - // resource handler for images and icons - registry - .addResourceHandler("/img/**") - .addResourceLocations("classpath:META-INF/resources/img/"); - registry - .addResourceHandler("/icons/**") - .addResourceLocations("classpath:META-INF/resources/icons/"); - } + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + // resource handler for images and icons + registry.addResourceHandler("/img/**").addResourceLocations("classpath:META-INF/resources/img/"); + registry.addResourceHandler("/icons/**").addResourceLocations("classpath:META-INF/resources/icons/"); + } + } diff --git a/src/main/java/org/karnak/backend/constant/EndPoint.java b/src/main/java/org/karnak/backend/constant/EndPoint.java index 73b35a90b..de2ddb508 100644 --- a/src/main/java/org/karnak/backend/constant/EndPoint.java +++ b/src/main/java/org/karnak/backend/constant/EndPoint.java @@ -11,14 +11,18 @@ public class EndPoint { - // Paths - public static final String ECHO_PATH = "/api/echo"; - public static final String DESTINATIONS_PATH = "/destinations"; - // public static final String FILE_PATH = "/file"; - // public static final String DOWNLOAD_SOPUID_PATH = "/download/aet/sopuid"; + // Paths + public static final String ECHO_PATH = "/api/echo"; + + public static final String DESTINATIONS_PATH = "/destinations"; + + // public static final String FILE_PATH = "/file"; + // public static final String DOWNLOAD_SOPUID_PATH = "/download/aet/sopuid"; + + // Params + public static final String SRC_AET_PARAM = "srcAet"; + + // public static final String AET_PARAM = "aet"; + // public static final String SOP_UID_PARAM = "sopUid"; - // Params - public static final String SRC_AET_PARAM = "srcAet"; - // public static final String AET_PARAM = "aet"; - // public static final String SOP_UID_PARAM = "sopUid"; } diff --git a/src/main/java/org/karnak/backend/constant/Notification.java b/src/main/java/org/karnak/backend/constant/Notification.java index 391c8b2ca..5b9bf6fb6 100644 --- a/src/main/java/org/karnak/backend/constant/Notification.java +++ b/src/main/java/org/karnak/backend/constant/Notification.java @@ -12,28 +12,39 @@ /** Constants for notification */ public class Notification { - // Default - public static final String DEFAULT_SUBJECT_ERROR_PREFIX = "**ERROR**"; - public static final String DEFAULT_SUBJECT_PATTERN = "[Karnak Notification] %s %.30s"; - public static final String DEFAULT_SUBJECT_VALUES = "PatientID,StudyDescription"; - public static final String DEFAULT_INTERVAL = "45"; - public static final String MAIL_SMTP_SENDER = "karnak@kehops.online"; - - // Thymeleaf - public static final String CONTEXT_THYMELEAF = "notif"; - public static final String TEMPLATE_THYMELEAF = "transferNotificationEmail"; - - // Separators - public static final String COMMA_SEPARATOR = ","; - public static final String EMPTY_STRING = ""; - public static final String SPACE = " "; - - // PARAMS - public static final String PARAM_STUDY_DATE = "StudyDate"; - public static final String PARAM_STUDY_INSTANCE_UID = "StudyInstanceUID"; - public static final String PARAM_STUDY_DESCRIPTION = "StudyDescription"; - public static final String PARAM_PATIENT_ID = "PatientID"; - - // Various - public static final long EXTRA_TIMER_DELAY = 10; + // Default + public static final String DEFAULT_SUBJECT_ERROR_PREFIX = "**ERROR**"; + + public static final String DEFAULT_SUBJECT_PATTERN = "[Karnak Notification] %s %.30s"; + + public static final String DEFAULT_SUBJECT_VALUES = "PatientID,StudyDescription"; + + public static final String DEFAULT_INTERVAL = "45"; + + public static final String MAIL_SMTP_SENDER = "karnak@kehops.online"; + + // Thymeleaf + public static final String CONTEXT_THYMELEAF = "notif"; + + public static final String TEMPLATE_THYMELEAF = "transferNotificationEmail"; + + // Separators + public static final String COMMA_SEPARATOR = ","; + + public static final String EMPTY_STRING = ""; + + public static final String SPACE = " "; + + // PARAMS + public static final String PARAM_STUDY_DATE = "StudyDate"; + + public static final String PARAM_STUDY_INSTANCE_UID = "StudyInstanceUID"; + + public static final String PARAM_STUDY_DESCRIPTION = "StudyDescription"; + + public static final String PARAM_PATIENT_ID = "PatientID"; + + // Various + public static final long EXTRA_TIMER_DELAY = 10; + } diff --git a/src/main/java/org/karnak/backend/constant/Token.java b/src/main/java/org/karnak/backend/constant/Token.java index 998fb471d..67b364baf 100644 --- a/src/main/java/org/karnak/backend/constant/Token.java +++ b/src/main/java/org/karnak/backend/constant/Token.java @@ -11,12 +11,17 @@ /** Constants dealing used for token management */ public class Token { - // Name of the resource in the access token for retrieving roles - public static final String RESOURCE_NAME = "karnak"; - // Access token resource access - public static final String RESOURCE_ACCESS = "resource_access"; - // Roles - public static final String ROLES = "roles"; - // Prefix of built roles - public static final String PREFIX_ROLE = "ROLE_"; + + // Name of the resource in the access token for retrieving roles + public static final String RESOURCE_NAME = "karnak"; + + // Access token resource access + public static final String RESOURCE_ACCESS = "resource_access"; + + // Roles + public static final String ROLES = "roles"; + + // Prefix of built roles + public static final String PREFIX_ROLE = "ROLE_"; + } diff --git a/src/main/java/org/karnak/backend/controller/EchoController.java b/src/main/java/org/karnak/backend/controller/EchoController.java index a91e78ac2..b8fd6a70d 100644 --- a/src/main/java/org/karnak/backend/controller/EchoController.java +++ b/src/main/java/org/karnak/backend/controller/EchoController.java @@ -38,58 +38,44 @@ @Tag(name = "Echo", description = "API Endpoints for Echo") public class EchoController { - private static final Logger LOGGER = LoggerFactory.getLogger(EchoController.class); + private static final Logger LOGGER = LoggerFactory.getLogger(EchoController.class); - // Services - private final EchoService echoService; + // Services + private final EchoService echoService; - /** - * Autowired constructor - * - * @param echoService Service managing echo - */ - @Autowired - public EchoController(final EchoService echoService) { - this.echoService = echoService; - } + /** + * Autowired constructor + * @param echoService Service managing echo + */ + @Autowired + public EchoController(final EchoService echoService) { + this.echoService = echoService; + } - @Operation( - summary = "Retrieve status destinations", - description = "Retrieve status and configured destinations from an AeTitle", - tags = "Echo") - @ApiResponses( - value = { - @ApiResponse( - responseCode = "200", - description = "Status and configured destinations found from an AeTitle", - content = - @Content( - schema = @Schema(implementation = DestinationEchos.class), - examples = - @ExampleObject( - name = "Example values status destinations", - value = SpringDocUtil.EXAMPLE_VALUES_STATUS_DESTINATIONS_ECHO))), - @ApiResponse(responseCode = "204", description = "No Content", content = @Content) - }) - /** - * Retrieve the status of the configured destinations from the source AeTitle in parameter - * - * @param srcAet Source AeTitle to get the destination from - * @return Configured destinations with theirs status - */ - @GetMapping( - value = {EndPoint.DESTINATIONS_PATH}, - produces = {MediaType.APPLICATION_XML_VALUE}) - public ResponseEntity retrieveStatusConfiguredDestinations( - @RequestParam(value = EndPoint.SRC_AET_PARAM) String srcAet) { + @Operation(summary = "Retrieve status destinations", + description = "Retrieve status and configured destinations from an AeTitle", tags = "Echo") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Status and configured destinations found from an AeTitle", + content = @Content(schema = @Schema(implementation = DestinationEchos.class), + examples = @ExampleObject(name = "Example values status destinations", + value = SpringDocUtil.EXAMPLE_VALUES_STATUS_DESTINATIONS_ECHO))), + @ApiResponse(responseCode = "204", description = "No Content", content = @Content) }) + /** + * Retrieve the status of the configured destinations from the source AeTitle in + * parameter + * @param srcAet Source AeTitle to get the destination from + * @return Configured destinations with theirs status + */ + @GetMapping(value = { EndPoint.DESTINATIONS_PATH }, produces = { MediaType.APPLICATION_XML_VALUE }) + public ResponseEntity retrieveStatusConfiguredDestinations( + @RequestParam(value = EndPoint.SRC_AET_PARAM) String srcAet) { - // Call service to retrieve the status of the configured destinations - List destinationEchos = - echoService.retrieveStatusConfiguredDestinations(srcAet); + // Call service to retrieve the status of the configured destinations + List destinationEchos = echoService.retrieveStatusConfiguredDestinations(srcAet); + + // If empty no content else list of destinations with status + return destinationEchos.isEmpty() ? ResponseEntity.noContent().build() + : ResponseEntity.ok(new DestinationEchos(destinationEchos)); + } - // If empty no content else list of destinations with status - return destinationEchos.isEmpty() - ? ResponseEntity.noContent().build() - : ResponseEntity.ok(new DestinationEchos(destinationEchos)); - } } diff --git a/src/main/java/org/karnak/backend/controller/FileController.java b/src/main/java/org/karnak/backend/controller/FileController.java index 71b25c061..47c7a9409 100644 --- a/src/main/java/org/karnak/backend/controller/FileController.java +++ b/src/main/java/org/karnak/backend/controller/FileController.java @@ -28,46 +28,46 @@ // @RequestMapping(EndPoint.FILE_PATH) // public class FileController { // -// private static final Logger LOGGER = LoggerFactory.getLogger(FileController.class); +// private static final Logger LOGGER = LoggerFactory.getLogger(FileController.class); // -// // Services -// private final FileService fileService; +// // Services +// private final FileService fileService; // -// /** -// * Autowired constructor -// * -// * @param fileService Service managing files -// */ -// @Autowired -// public FileController(final FileService fileService) { -// this.fileService = fileService; -// } +// /** +// * Autowired constructor +// * +// * @param fileService Service managing files +// */ +// @Autowired +// public FileController(final FileService fileService) { +// this.fileService = fileService; +// } // -// /** -// * @param aet Aet to get files from -// * @param fileName File to download -// * @return if successful download the file otherwise display an error message -// */ -// @GetMapping( -// value = {EndPoint.DOWNLOAD_SOPUID_PATH}, -// produces = {MediaType.APPLICATION_OCTET_STREAM_VALUE}) -// public ResponseEntity downloadSopUidFromAetT( -// @RequestParam(value = EndPoint.AET_PARAM) String aet, -// @RequestParam(value = EndPoint.SOP_UID_PARAM) String fileName) { -// byte[] file; +// /** +// * @param aet Aet to get files from +// * @param fileName File to download +// * @return if successful download the file otherwise display an error message +// */ +// @GetMapping( +// value = {EndPoint.DOWNLOAD_SOPUID_PATH}, +// produces = {MediaType.APPLICATION_OCTET_STREAM_VALUE}) +// public ResponseEntity downloadSopUidFromAetT( +// @RequestParam(value = EndPoint.AET_PARAM) String aet, +// @RequestParam(value = EndPoint.SOP_UID_PARAM) String fileName) { +// byte[] file; // -// try { -// file = fileService.retrieveFileToDownload(aet, fileName); -// } catch (Exception e) { -// LOGGER.error("Unexpected exception when downloading", e); -// return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) -// .body("Error when downloading the file: Internal server error => " + e.getMessage()); -// } +// try { +// file = fileService.retrieveFileToDownload(aet, fileName); +// } catch (Exception e) { +// LOGGER.error("Unexpected exception when downloading", e); +// return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) +// .body("Error when downloading the file: Internal server error => " + e.getMessage()); +// } // -// return file == null -// ? ResponseEntity.notFound().build() -// : ResponseEntity.status(HttpStatus.OK) -// .header("Content-Disposition", "attachment; filename=\"" + fileName + "\"") -// .body(file); -// } +// return file == null +// ? ResponseEntity.notFound().build() +// : ResponseEntity.status(HttpStatus.OK) +// .header("Content-Disposition", "attachment; filename=\"" + fileName + "\"") +// .body(file); +// } // } diff --git a/src/main/java/org/karnak/backend/data/converter/ArgumentToMapConverter.java b/src/main/java/org/karnak/backend/data/converter/ArgumentToMapConverter.java index baf645478..e6ca2f37a 100644 --- a/src/main/java/org/karnak/backend/data/converter/ArgumentToMapConverter.java +++ b/src/main/java/org/karnak/backend/data/converter/ArgumentToMapConverter.java @@ -15,16 +15,15 @@ import java.util.Map; import org.karnak.backend.data.entity.ArgumentEntity; -public class ArgumentToMapConverter - extends StdConverter, Map> { +public class ArgumentToMapConverter extends StdConverter, Map> { + + @Override + public Map convert(List argumentEntities) { + Map argumentMap = new HashMap<>(); + argumentEntities.forEach(argument -> { + argumentMap.put(argument.getKey(), argument.getValue()); + }); + return argumentMap; + } - @Override - public Map convert(List argumentEntities) { - Map argumentMap = new HashMap<>(); - argumentEntities.forEach( - argument -> { - argumentMap.put(argument.getKey(), argument.getValue()); - }); - return argumentMap; - } } diff --git a/src/main/java/org/karnak/backend/data/converter/RectangleListConverter.java b/src/main/java/org/karnak/backend/data/converter/RectangleListConverter.java index 5ee9c3ab0..5f7898df0 100644 --- a/src/main/java/org/karnak/backend/data/converter/RectangleListConverter.java +++ b/src/main/java/org/karnak/backend/data/converter/RectangleListConverter.java @@ -19,40 +19,32 @@ @Converter public class RectangleListConverter implements AttributeConverter, String> { - private static final String SPLIT_CHAR = ";"; - - public static String rectangleToString(Rectangle rect) { - return String.join( - " ", - String.valueOf(rect.x), - String.valueOf(rect.y), - String.valueOf(rect.width), - String.valueOf(rect.height)); - } - - public static Rectangle stringToRectangle(String rectangle) { - String[] vals = rectangle.trim().split("\\s+"); - if (vals.length == 4) { - return new Rectangle( - Integer.parseInt(vals[0]), - Integer.parseInt(vals[1]), - Integer.parseInt(vals[2]), - Integer.parseInt(vals[3])); - } - return null; - } - - @Override - public String convertToDatabaseColumn(List stringList) { - return stringList.stream() - .map(RectangleListConverter::rectangleToString) - .collect(Collectors.joining(SPLIT_CHAR)); - } - - @Override - public List convertToEntityAttribute(String string) { - return Arrays.asList(string.split(SPLIT_CHAR)).stream() - .map(RectangleListConverter::stringToRectangle) - .collect(Collectors.toList()); - } + private static final String SPLIT_CHAR = ";"; + + public static String rectangleToString(Rectangle rect) { + return String.join(" ", String.valueOf(rect.x), String.valueOf(rect.y), String.valueOf(rect.width), + String.valueOf(rect.height)); + } + + public static Rectangle stringToRectangle(String rectangle) { + String[] vals = rectangle.trim().split("\\s+"); + if (vals.length == 4) { + return new Rectangle(Integer.parseInt(vals[0]), Integer.parseInt(vals[1]), Integer.parseInt(vals[2]), + Integer.parseInt(vals[3])); + } + return null; + } + + @Override + public String convertToDatabaseColumn(List stringList) { + return stringList.stream().map(RectangleListConverter::rectangleToString) + .collect(Collectors.joining(SPLIT_CHAR)); + } + + @Override + public List convertToEntityAttribute(String string) { + return Arrays.asList(string.split(SPLIT_CHAR)).stream().map(RectangleListConverter::stringToRectangle) + .collect(Collectors.toList()); + } + } diff --git a/src/main/java/org/karnak/backend/data/converter/RectangleListToStringListConverter.java b/src/main/java/org/karnak/backend/data/converter/RectangleListToStringListConverter.java index 6c3ed2ced..c2089b3b4 100644 --- a/src/main/java/org/karnak/backend/data/converter/RectangleListToStringListConverter.java +++ b/src/main/java/org/karnak/backend/data/converter/RectangleListToStringListConverter.java @@ -14,22 +14,16 @@ import java.util.ArrayList; import java.util.List; -public class RectangleListToStringListConverter - extends StdConverter, List> { +public class RectangleListToStringListConverter extends StdConverter, List> { + + @Override + public List convert(List rectangles) { + List strArray = new ArrayList(); + rectangles.forEach(rectangle -> { + strArray.add(String.format("%d %d %d %d", (int) rectangle.getX(), (int) rectangle.getY(), + (int) rectangle.getWidth(), (int) rectangle.getHeight())); + }); + return strArray; + } - @Override - public List convert(List rectangles) { - List strArray = new ArrayList(); - rectangles.forEach( - rectangle -> { - strArray.add( - String.format( - "%d %d %d %d", - (int) rectangle.getX(), - (int) rectangle.getY(), - (int) rectangle.getWidth(), - (int) rectangle.getHeight())); - }); - return strArray; - } } diff --git a/src/main/java/org/karnak/backend/data/converter/TagListToStringListConverter.java b/src/main/java/org/karnak/backend/data/converter/TagListToStringListConverter.java index d3e76631f..9e2d60a4c 100644 --- a/src/main/java/org/karnak/backend/data/converter/TagListToStringListConverter.java +++ b/src/main/java/org/karnak/backend/data/converter/TagListToStringListConverter.java @@ -17,13 +17,13 @@ // https://www.logicbig.com/tutorials/misc/jackson/json-serialize-deserialize-converter.html public class TagListToStringListConverter extends StdConverter, List> { - @Override - public List convert(List tagEntities) { - List strArray = new ArrayList(); - tagEntities.forEach( - tagEntity -> { - strArray.add(tagEntity.getTagValue()); - }); - return strArray; - } + @Override + public List convert(List tagEntities) { + List strArray = new ArrayList(); + tagEntities.forEach(tagEntity -> { + strArray.add(tagEntity.getTagValue()); + }); + return strArray; + } + } diff --git a/src/main/java/org/karnak/backend/data/entity/ArgumentEntity.java b/src/main/java/org/karnak/backend/data/entity/ArgumentEntity.java index 9458429e4..7c5e8ecee 100644 --- a/src/main/java/org/karnak/backend/data/entity/ArgumentEntity.java +++ b/src/main/java/org/karnak/backend/data/entity/ArgumentEntity.java @@ -24,79 +24,82 @@ @Table(name = "arguments") public class ArgumentEntity implements Serializable { - private static final long serialVersionUID = -839421871919135822L; - - private Long id; - private ProfileElementEntity profileElementEntity; - private String key; - private String value; - - public ArgumentEntity() {} - - public ArgumentEntity(String key, String value) { - this.key = key; - this.value = value; - } - - public ArgumentEntity(String key, String value, ProfileElementEntity profileElementEntity) { - this.key = key; - this.value = value; - this.profileElementEntity = profileElementEntity; - } - - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - @JsonIgnore - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public String getKey() { - return key; - } - - public void setKey(String key) { - this.key = key; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - - @ManyToOne() - @JoinColumn(name = "profile_element_id", nullable = false) - public ProfileElementEntity getProfileElementEntity() { - return profileElementEntity; - } - - public void setProfileElementEntity(ProfileElementEntity profileElementEntity) { - this.profileElementEntity = profileElementEntity; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - ArgumentEntity that = (ArgumentEntity) o; - return Objects.equals(id, that.id) - && Objects.equals(key, that.key) - && Objects.equals(value, that.value); - } - - @Override - public int hashCode() { - return Objects.hash(id, key, value); - } + private static final long serialVersionUID = -839421871919135822L; + + private Long id; + + private ProfileElementEntity profileElementEntity; + + private String key; + + private String value; + + public ArgumentEntity() { + } + + public ArgumentEntity(String key, String value) { + this.key = key; + this.value = value; + } + + public ArgumentEntity(String key, String value, ProfileElementEntity profileElementEntity) { + this.key = key; + this.value = value; + this.profileElementEntity = profileElementEntity; + } + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + @JsonIgnore + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + @ManyToOne() + @JoinColumn(name = "profile_element_id", nullable = false) + public ProfileElementEntity getProfileElementEntity() { + return profileElementEntity; + } + + public void setProfileElementEntity(ProfileElementEntity profileElementEntity) { + this.profileElementEntity = profileElementEntity; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ArgumentEntity that = (ArgumentEntity) o; + return Objects.equals(id, that.id) && Objects.equals(key, that.key) && Objects.equals(value, that.value); + } + + @Override + public int hashCode() { + return Objects.hash(id, key, value); + } + } diff --git a/src/main/java/org/karnak/backend/data/entity/DestinationEntity.java b/src/main/java/org/karnak/backend/data/entity/DestinationEntity.java index e462ec7bb..53bb0fc11 100644 --- a/src/main/java/org/karnak/backend/data/entity/DestinationEntity.java +++ b/src/main/java/org/karnak/backend/data/entity/DestinationEntity.java @@ -49,682 +49,637 @@ @Table(name = "destination") public class DestinationEntity implements Serializable { - private static final long serialVersionUID = 4835879567037810171L; - - private Long id; - private String description; - private DestinationType destinationType; - - private boolean activate; - private String condition; - - private boolean desidentification; - private String issuerByDefault; - - private PseudonymType pseudonymType; - - private String tag; - private String delimiter; - private Integer position; - private Boolean savePseudonym; - private boolean filterBySOPClasses; - private Set SOPClassUIDEntityFilters = new HashSet<>(); - private List kheopsAlbumEntities; - private ProjectEntity projectEntity; - private ForwardNodeEntity forwardNodeEntity; - - // Activate notification - private boolean activateNotification; - - // list of emails (comma separated) used when the images have been sent (or - // partially sent) to the final destination. Note: if an issue appears before - // sending to the final destination then no email is delivered. - private String notify; - - // Prefix of the email object when containing an issue. Default value: **ERROR** - private String notifyObjectErrorPrefix; - - // Pattern of the email object, see https://dzone.com/articles/java-string-format-examples. - // Default value: - // [Karnak Notification] %s %.30s - private String notifyObjectPattern; - - // Values injected in the pattern [PatientID StudyDescription StudyDate - // StudyInstanceUID]. Default value: PatientID,StudyDescription - private String notifyObjectValues; - - // Interval in seconds for sending a notification (when no new image is arrived - // in the archive folder). Default value: 45 - private Integer notifyInterval; - - // DICOM properties - // the AETitle of the destination node. - // mandatory[type=dicom] - private String aeTitle; - // the host or IP of the destination node. - // mandatory[type=dicom] - private String hostname; - // the port of the destination node. - // mandatory[type=dicom] - private Integer port; - // false by default; if "true" then use the destination AETitle as the calling - // AETitle at the gateway side. Otherwise with "false" the calling AETitle is - // the AETitle defined in the property "listener.aet" of the file - // gateway.properties. - private Boolean useaetdest; - - // STOW properties - // the destination STOW-RS URL. - // mandatory[type=stow] - private String url; - // credentials of the STOW-RS service (format is "user:password"). - private String urlCredentials; - // headers for HTTP request. - private String headers; - - // UID corresponding to the Transfer Syntax - private String transferSyntax; - - // Transcode Only Uncompressed - private boolean transcodeOnlyUncompressed; - - // Flag to know if there are some transfer activities on this destination - private boolean transferInProgress; - - // Date of the last transfer for this destination - private LocalDateTime lastTransfer; - - // Last date of the check of email notifications for this destination - private LocalDateTime emailLastCheck; - - public DestinationEntity() { - this(null); - } - - protected DestinationEntity(DestinationType destinationType) { - this.destinationType = destinationType; - this.activate = true; - this.condition = ""; - this.description = ""; - this.desidentification = false; - this.issuerByDefault = ""; - this.pseudonymType = PseudonymType.MAINZELLISTE_PID; - this.tag = null; - this.delimiter = null; - this.position = null; - this.savePseudonym = null; - this.filterBySOPClasses = false; - - this.notify = ""; - this.notifyObjectErrorPrefix = ""; - this.notifyObjectPattern = ""; - this.notifyObjectValues = ""; - this.notifyInterval = 0; - this.aeTitle = ""; - this.hostname = ""; - this.port = 0; - this.useaetdest = Boolean.FALSE; - this.url = ""; - this.urlCredentials = ""; - this.headers = ""; - - this.transcodeOnlyUncompressed = true; - } - - public static DestinationEntity ofDicomEmpty() { - return new DestinationEntity(DestinationType.dicom); - } - - public static DestinationEntity ofDicom( - String description, String aeTitle, String hostname, int port, Boolean useaetdest) { - DestinationEntity destinationEntity = new DestinationEntity(DestinationType.dicom); - destinationEntity.setDescription(description); - destinationEntity.setAeTitle(aeTitle); - destinationEntity.setHostname(hostname); - destinationEntity.setPort(Integer.valueOf(port)); - destinationEntity.setUseaetdest(useaetdest); - return destinationEntity; - } - - public static DestinationEntity ofStowEmpty() { - return new DestinationEntity(DestinationType.stow); - } - - public static DestinationEntity ofStow( - String description, String url, String urlCredentials, String headers) { - DestinationEntity destinationEntity = new DestinationEntity(DestinationType.stow); - destinationEntity.setDescription(description); - destinationEntity.setUrl(url); - destinationEntity.setUrlCredentials(urlCredentials); - destinationEntity.setHeaders(headers); - return destinationEntity; - } - - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public boolean isActivate() { - return activate; - } - - public void setActivate(boolean activate) { - this.activate = activate; - } - - public String getCondition() { - return condition; - } - - public void setCondition(String condition) { - this.condition = condition; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - @NotNull(message = "Type is mandatory") - @Column(name = "type") - public DestinationType getDestinationType() { - return destinationType; - } - - public void setDestinationType(DestinationType destinationType) { - this.destinationType = destinationType; - } - - public boolean isDesidentification() { - return desidentification; - } - - public void setDesidentification(boolean desidentification) { - this.desidentification = desidentification; - } - - public String getIssuerByDefault() { - return issuerByDefault; - } - - public void setIssuerByDefault(String issuerByDefault) { - this.issuerByDefault = issuerByDefault; - } - - public boolean isFilterBySOPClasses() { - return filterBySOPClasses; - } - - public void setFilterBySOPClasses(boolean filterBySOPClasses) { - this.filterBySOPClasses = filterBySOPClasses; - } - - public String getNotify() { - return notify; - } - - public void setNotify(String notify) { - this.notify = notify; - } - - public String getNotifyObjectErrorPrefix() { - return notifyObjectErrorPrefix; - } - - public void setNotifyObjectErrorPrefix(String notifyObjectErrorPrefix) { - this.notifyObjectErrorPrefix = notifyObjectErrorPrefix; - } - - public String getNotifyObjectPattern() { - return notifyObjectPattern; - } - - public void setNotifyObjectPattern(String notifyObjectPattern) { - this.notifyObjectPattern = notifyObjectPattern; - } - - public String getNotifyObjectValues() { - return notifyObjectValues; - } - - public void setNotifyObjectValues(String notifyObjectValues) { - this.notifyObjectValues = notifyObjectValues; - } - - public Integer getNotifyInterval() { - return notifyInterval; - } - - public void setNotifyInterval(Integer notifyInterval) { - this.notifyInterval = notifyInterval; - } - - @NotBlank(groups = DestinationDicomGroup.class, message = "AETitle is mandatory") - @Size( - groups = DestinationDicomGroup.class, - max = 16, - message = "AETitle has more than 16 characters") - public String getAeTitle() { - return aeTitle; - } - - public void setAeTitle(String aeTitle) { - this.aeTitle = aeTitle; - } - - @NotBlank(groups = DestinationDicomGroup.class, message = "Hostname is mandatory") - public String getHostname() { - return hostname; - } - - public void setHostname(String hostname) { - this.hostname = hostname; - } - - @NotNull(groups = DestinationDicomGroup.class, message = "Port is mandatory") - @Min( - groups = DestinationDicomGroup.class, - value = 1, - message = "Port should be between 1 and 65535") - @Max( - groups = DestinationDicomGroup.class, - value = 65535, - message = "Port should be between 1 and 65535") - public Integer getPort() { - return port; - } - - public void setPort(Integer port) { - this.port = port; - } - - public Boolean getUseaetdest() { - return useaetdest; - } - - public void setUseaetdest(Boolean useaetdest) { - this.useaetdest = useaetdest; - } - - @NotBlank(groups = DestinationStowGroup.class, message = "URL is mandatory") - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - public String getUrlCredentials() { - return urlCredentials; - } - - public void setUrlCredentials(String urlCredentials) { - this.urlCredentials = urlCredentials; - } - - @Size(max = 4096, message = "Headers has more than 4096 characters") - public String getHeaders() { - return headers; - } - - public void setHeaders(String headers) { - this.headers = headers; - } - - @JsonGetter("forwardNode") - @ManyToOne - @JoinColumn(name = "forward_node_id") - public ForwardNodeEntity getForwardNodeEntity() { - return forwardNodeEntity; - } - - @JsonSetter("forwardNode") - public void setForwardNodeEntity(ForwardNodeEntity forwardNodeEntity) { - this.forwardNodeEntity = forwardNodeEntity; - } - - @ManyToMany(fetch = FetchType.EAGER) - @JoinTable( - name = "sop_class_filter", - joinColumns = @JoinColumn(name = "destination_id"), - inverseJoinColumns = @JoinColumn(name = "sop_class_uid_id")) - public Set getSOPClassUIDEntityFilters() { - return this.SOPClassUIDEntityFilters; - } - - public void setSOPClassUIDEntityFilters(Set sopClassUIDEntities) { - this.SOPClassUIDEntityFilters = sopClassUIDEntities; - } - - public Set retrieveSOPClassUIDFiltersName() { - Set sopList = new HashSet<>(); - this.SOPClassUIDEntityFilters.forEach(sopClassUID -> sopList.add(sopClassUID.getName())); - return sopList; - } - - public PseudonymType getPseudonymType() { - return pseudonymType; - } - - public void setPseudonymType(PseudonymType pseudonymType) { - this.pseudonymType = pseudonymType; - } - - public String getTag() { - return tag; - } - - public void setTag(String tag) { - this.tag = tag; - } - - public String getDelimiter() { - return delimiter; - } - - public void setDelimiter(String delimiter) { - this.delimiter = delimiter; - } - - public Integer getPosition() { - return position; - } - - public void setPosition(Integer position) { - this.position = position; - } - - public Boolean getSavePseudonym() { - return savePseudonym; - } - - public void setSavePseudonym(Boolean savePseudonym) { - this.savePseudonym = savePseudonym; - } - - @JsonGetter("kheopsAlbums") - @OneToMany(mappedBy = "destinationEntity", cascade = CascadeType.REMOVE) - @LazyCollection(LazyCollectionOption.FALSE) - public List getKheopsAlbumEntities() { - return kheopsAlbumEntities; - } - - @JsonSetter("kheopsAlbums") - public void setKheopsAlbumEntities(List kheopsAlbumEntities) { - this.kheopsAlbumEntities = kheopsAlbumEntities; - } - - @JsonGetter("project") - @ManyToOne - @JoinColumn(name = "project_id") - public ProjectEntity getProjectEntity() { - return projectEntity; - } - - @JsonSetter("project") - public void setProjectEntity(ProjectEntity projectEntity) { - this.projectEntity = projectEntity; - } - - public boolean isActivateNotification() { - return activateNotification; - } - - public void setActivateNotification(boolean activateNotification) { - this.activateNotification = activateNotification; - } - - public String getTransferSyntax() { - return transferSyntax; - } - - public void setTransferSyntax(String transferSyntax) { - this.transferSyntax = transferSyntax; - } - - public boolean isTranscodeOnlyUncompressed() { - return transcodeOnlyUncompressed; - } - - public void setTranscodeOnlyUncompressed(boolean transcodeOnlyUncompressed) { - this.transcodeOnlyUncompressed = transcodeOnlyUncompressed; - } - - public boolean isTransferInProgress() { - return transferInProgress; - } - - public void setTransferInProgress(boolean transferInProgress) { - this.transferInProgress = transferInProgress; - } - - public LocalDateTime getEmailLastCheck() { - return emailLastCheck; - } - - public void setEmailLastCheck(LocalDateTime emailLastCheck) { - this.emailLastCheck = emailLastCheck; - } - - public LocalDateTime getLastTransfer() { - return lastTransfer; - } - - public void setLastTransfer(LocalDateTime lastTransfer) { - this.lastTransfer = lastTransfer; - } - - /** - * Informs if this object matches with the filter as text. - * - * @param filterText the filter as text. - * @return true if this object matches with the filter as text; false otherwise. - */ - public boolean matchesFilter(String filterText) { - return contains(description, filterText) // - || contains(notify, filterText) // - || contains(notifyObjectErrorPrefix, filterText) // - || contains(notifyObjectPattern, filterText) // - || contains(notifyObjectValues, filterText) // - || contains(aeTitle, filterText) // - || contains(hostname, filterText) // - || equals(port, filterText) // - || contains(url, filterText) // - || contains(urlCredentials, filterText) // - || contains(headers, filterText); - } - - private boolean contains(String value, String filterText) { - return value != null && value.contains(filterText); - } - - private boolean equals(Integer value, String filterText) { - return value != null && value.toString().equals(filterText); - } - - @Override - public String toString() { - if (destinationType != null) { - switch (destinationType) { - case dicom: - return "Destination [id=" - + id - + ", description=" - + description - + ", type=" - + destinationType - + ", notify=" - + notify - + ", notifyObjectErrorPrefix=" - + notifyObjectErrorPrefix - + ", notifyObjectPattern=" - + notifyObjectPattern - + ", notifyObjectValues=" - + notifyObjectValues - + ", notifyInterval=" - + notifyInterval - + ", aeTitle=" - + aeTitle - + ", hostname=" - + hostname - + ", port=" - + port - + ", useaetdest=" - + useaetdest - + "]"; - case stow: - return "Destination [id=" - + id - + ", description=" - + description - + ", type=" - + destinationType - + ", notify=" - + notify - + ", notifyObjectErrorPrefix=" - + notifyObjectErrorPrefix - + ", notifyObjectPattern=" - + notifyObjectPattern - + ", notifyObjectValues=" - + notifyObjectValues - + ", notifyInterval=" - + notifyInterval - + ", url=" - + url - + ", urlCredentials=" - + urlCredentials - + ", headers=" - + headers - + "]"; - } - } - return "Destination [id=" - + id - + ", description=" - + description - + ", type=" - + destinationType - + ", notify=" - + notify - + ", notifyObjectErrorPrefix=" - + notifyObjectErrorPrefix - + ", notifyObjectPattern=" - + notifyObjectPattern - + ", notifyObjectValues=" - + notifyObjectValues - + ", notifyInterval=" - + notifyInterval - + "]"; - } - - public String retrieveStringReference() { - if (destinationType != null) { - switch (destinationType) { - case dicom: - return getAeTitle(); - case stow: - return getUrl() + ":" + getPort(); - } - } - return "Type of destination is unknown"; - } - // - // @Override - // public boolean equals(Object o) { - // if (this == o) { - // return true; - // } - // if (o == null || getClass() != o.getClass()) { - // return false; - // } - // DestinationEntity that = (DestinationEntity) o; - // return desidentification == that.desidentification - // && issuerByDefault == that.issuerByDefault - // && filterBySOPClasses == that.filterBySOPClasses - // && Objects.equals(id, that.id) - // && Objects.equals(description, that.description) - // && destinationType == that.destinationType - // && pseudonymType == that.pseudonymType - // && Objects.equals(tag, that.tag) - // && Objects.equals(delimiter, that.delimiter) - // && Objects.equals(position, that.position) - // && Objects.equals(savePseudonym, that.savePseudonym) - // && Objects.equals(transferSyntax, that.transferSyntax) - // && Objects.equals(transcodeOnlyUncompressed, that.transcodeOnlyUncompressed) - // && Objects.equals(activateNotification, that.activateNotification) - // && Objects.equals(notify, that.notify) - // && Objects.equals(notifyObjectErrorPrefix, that.notifyObjectErrorPrefix) - // && Objects.equals(notifyObjectPattern, that.notifyObjectPattern) - // && Objects.equals(notifyObjectValues, that.notifyObjectValues) - // && Objects.equals(notifyInterval, that.notifyInterval) - // && Objects.equals(aeTitle, that.aeTitle) - // && Objects.equals(hostname, that.hostname) - // && Objects.equals(port, that.port) - // && Objects.equals(useaetdest, that.useaetdest) - // && Objects.equals(url, that.url) - // && Objects.equals(urlCredentials, that.urlCredentials) - // && Objects.equals(headers, that.headers); - // } - // - // @Override - // public int hashCode() { - // return Objects.hash( - // id, - // description, - // destinationType, - // desidentification, - // issuerByDefault, - // pseudonymType, - // tag, - // delimiter, - // position, - // savePseudonym, - // filterBySOPClasses, - // transferSyntax, - // transcodeOnlyUncompressed, - // activateNotification, - // notify, - // notifyObjectErrorPrefix, - // notifyObjectPattern, - // notifyObjectValues, - // notifyInterval, - // aeTitle, - // hostname, - // port, - // useaetdest, - // url, - // urlCredentials, - // headers); - // } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - DestinationEntity that = (DestinationEntity) o; - return Objects.equals(id, that.id); - } - - @Override - public int hashCode() { - return Objects.hash(id); - } - - public String toStringDicomNotificationDestination() { - return "Host=" + getHostname() + " AET=" + getAeTitle() + " Port=" + getPort(); - } + private static final long serialVersionUID = 4835879567037810171L; + + private Long id; + + private String description; + + private DestinationType destinationType; + + private boolean activate; + + private String condition; + + private boolean desidentification; + + private String issuerByDefault; + + private PseudonymType pseudonymType; + + private String tag; + + private String delimiter; + + private Integer position; + + private Boolean savePseudonym; + + private boolean filterBySOPClasses; + + private Set SOPClassUIDEntityFilters = new HashSet<>(); + + private List kheopsAlbumEntities; + + private ProjectEntity projectEntity; + + private ForwardNodeEntity forwardNodeEntity; + + // Activate notification + private boolean activateNotification; + + // list of emails (comma separated) used when the images have been sent (or + // partially sent) to the final destination. Note: if an issue appears before + // sending to the final destination then no email is delivered. + private String notify; + + // Prefix of the email object when containing an issue. Default value: **ERROR** + private String notifyObjectErrorPrefix; + + // Pattern of the email object, see + // https://dzone.com/articles/java-string-format-examples. + // Default value: + // [Karnak Notification] %s %.30s + private String notifyObjectPattern; + + // Values injected in the pattern [PatientID StudyDescription StudyDate + // StudyInstanceUID]. Default value: PatientID,StudyDescription + private String notifyObjectValues; + + // Interval in seconds for sending a notification (when no new image is arrived + // in the archive folder). Default value: 45 + private Integer notifyInterval; + + // DICOM properties + // the AETitle of the destination node. + // mandatory[type=dicom] + private String aeTitle; + + // the host or IP of the destination node. + // mandatory[type=dicom] + private String hostname; + + // the port of the destination node. + // mandatory[type=dicom] + private Integer port; + + // false by default; if "true" then use the destination AETitle as the calling + // AETitle at the gateway side. Otherwise with "false" the calling AETitle is + // the AETitle defined in the property "listener.aet" of the file + // gateway.properties. + private Boolean useaetdest; + + // STOW properties + // the destination STOW-RS URL. + // mandatory[type=stow] + private String url; + + // credentials of the STOW-RS service (format is "user:password"). + private String urlCredentials; + + // headers for HTTP request. + private String headers; + + // UID corresponding to the Transfer Syntax + private String transferSyntax; + + // Transcode Only Uncompressed + private boolean transcodeOnlyUncompressed; + + // Flag to know if there are some transfer activities on this destination + private boolean transferInProgress; + + // Date of the last transfer for this destination + private LocalDateTime lastTransfer; + + // Last date of the check of email notifications for this destination + private LocalDateTime emailLastCheck; + + public DestinationEntity() { + this(null); + } + + protected DestinationEntity(DestinationType destinationType) { + this.destinationType = destinationType; + this.activate = true; + this.condition = ""; + this.description = ""; + this.desidentification = false; + this.issuerByDefault = ""; + this.pseudonymType = PseudonymType.MAINZELLISTE_PID; + this.tag = null; + this.delimiter = null; + this.position = null; + this.savePseudonym = null; + this.filterBySOPClasses = false; + + this.notify = ""; + this.notifyObjectErrorPrefix = ""; + this.notifyObjectPattern = ""; + this.notifyObjectValues = ""; + this.notifyInterval = 0; + this.aeTitle = ""; + this.hostname = ""; + this.port = 0; + this.useaetdest = Boolean.FALSE; + this.url = ""; + this.urlCredentials = ""; + this.headers = ""; + + this.transcodeOnlyUncompressed = true; + } + + public static DestinationEntity ofDicomEmpty() { + return new DestinationEntity(DestinationType.dicom); + } + + public static DestinationEntity ofDicom(String description, String aeTitle, String hostname, int port, + Boolean useaetdest) { + DestinationEntity destinationEntity = new DestinationEntity(DestinationType.dicom); + destinationEntity.setDescription(description); + destinationEntity.setAeTitle(aeTitle); + destinationEntity.setHostname(hostname); + destinationEntity.setPort(Integer.valueOf(port)); + destinationEntity.setUseaetdest(useaetdest); + return destinationEntity; + } + + public static DestinationEntity ofStowEmpty() { + return new DestinationEntity(DestinationType.stow); + } + + public static DestinationEntity ofStow(String description, String url, String urlCredentials, String headers) { + DestinationEntity destinationEntity = new DestinationEntity(DestinationType.stow); + destinationEntity.setDescription(description); + destinationEntity.setUrl(url); + destinationEntity.setUrlCredentials(urlCredentials); + destinationEntity.setHeaders(headers); + return destinationEntity; + } + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public boolean isActivate() { + return activate; + } + + public void setActivate(boolean activate) { + this.activate = activate; + } + + public String getCondition() { + return condition; + } + + public void setCondition(String condition) { + this.condition = condition; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + @NotNull(message = "Type is mandatory") + @Column(name = "type") + public DestinationType getDestinationType() { + return destinationType; + } + + public void setDestinationType(DestinationType destinationType) { + this.destinationType = destinationType; + } + + public boolean isDesidentification() { + return desidentification; + } + + public void setDesidentification(boolean desidentification) { + this.desidentification = desidentification; + } + + public String getIssuerByDefault() { + return issuerByDefault; + } + + public void setIssuerByDefault(String issuerByDefault) { + this.issuerByDefault = issuerByDefault; + } + + public boolean isFilterBySOPClasses() { + return filterBySOPClasses; + } + + public void setFilterBySOPClasses(boolean filterBySOPClasses) { + this.filterBySOPClasses = filterBySOPClasses; + } + + public String getNotify() { + return notify; + } + + public void setNotify(String notify) { + this.notify = notify; + } + + public String getNotifyObjectErrorPrefix() { + return notifyObjectErrorPrefix; + } + + public void setNotifyObjectErrorPrefix(String notifyObjectErrorPrefix) { + this.notifyObjectErrorPrefix = notifyObjectErrorPrefix; + } + + public String getNotifyObjectPattern() { + return notifyObjectPattern; + } + + public void setNotifyObjectPattern(String notifyObjectPattern) { + this.notifyObjectPattern = notifyObjectPattern; + } + + public String getNotifyObjectValues() { + return notifyObjectValues; + } + + public void setNotifyObjectValues(String notifyObjectValues) { + this.notifyObjectValues = notifyObjectValues; + } + + public Integer getNotifyInterval() { + return notifyInterval; + } + + public void setNotifyInterval(Integer notifyInterval) { + this.notifyInterval = notifyInterval; + } + + @NotBlank(groups = DestinationDicomGroup.class, message = "AETitle is mandatory") + @Size(groups = DestinationDicomGroup.class, max = 16, message = "AETitle has more than 16 characters") + public String getAeTitle() { + return aeTitle; + } + + public void setAeTitle(String aeTitle) { + this.aeTitle = aeTitle; + } + + @NotBlank(groups = DestinationDicomGroup.class, message = "Hostname is mandatory") + public String getHostname() { + return hostname; + } + + public void setHostname(String hostname) { + this.hostname = hostname; + } + + @NotNull(groups = DestinationDicomGroup.class, message = "Port is mandatory") + @Min(groups = DestinationDicomGroup.class, value = 1, message = "Port should be between 1 and 65535") + @Max(groups = DestinationDicomGroup.class, value = 65535, message = "Port should be between 1 and 65535") + public Integer getPort() { + return port; + } + + public void setPort(Integer port) { + this.port = port; + } + + public Boolean getUseaetdest() { + return useaetdest; + } + + public void setUseaetdest(Boolean useaetdest) { + this.useaetdest = useaetdest; + } + + @NotBlank(groups = DestinationStowGroup.class, message = "URL is mandatory") + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getUrlCredentials() { + return urlCredentials; + } + + public void setUrlCredentials(String urlCredentials) { + this.urlCredentials = urlCredentials; + } + + @Size(max = 4096, message = "Headers has more than 4096 characters") + public String getHeaders() { + return headers; + } + + public void setHeaders(String headers) { + this.headers = headers; + } + + @JsonGetter("forwardNode") + @ManyToOne + @JoinColumn(name = "forward_node_id") + public ForwardNodeEntity getForwardNodeEntity() { + return forwardNodeEntity; + } + + @JsonSetter("forwardNode") + public void setForwardNodeEntity(ForwardNodeEntity forwardNodeEntity) { + this.forwardNodeEntity = forwardNodeEntity; + } + + @ManyToMany(fetch = FetchType.EAGER) + @JoinTable(name = "sop_class_filter", joinColumns = @JoinColumn(name = "destination_id"), + inverseJoinColumns = @JoinColumn(name = "sop_class_uid_id")) + public Set getSOPClassUIDEntityFilters() { + return this.SOPClassUIDEntityFilters; + } + + public void setSOPClassUIDEntityFilters(Set sopClassUIDEntities) { + this.SOPClassUIDEntityFilters = sopClassUIDEntities; + } + + public Set retrieveSOPClassUIDFiltersName() { + Set sopList = new HashSet<>(); + this.SOPClassUIDEntityFilters.forEach(sopClassUID -> sopList.add(sopClassUID.getName())); + return sopList; + } + + public PseudonymType getPseudonymType() { + return pseudonymType; + } + + public void setPseudonymType(PseudonymType pseudonymType) { + this.pseudonymType = pseudonymType; + } + + public String getTag() { + return tag; + } + + public void setTag(String tag) { + this.tag = tag; + } + + public String getDelimiter() { + return delimiter; + } + + public void setDelimiter(String delimiter) { + this.delimiter = delimiter; + } + + public Integer getPosition() { + return position; + } + + public void setPosition(Integer position) { + this.position = position; + } + + public Boolean getSavePseudonym() { + return savePseudonym; + } + + public void setSavePseudonym(Boolean savePseudonym) { + this.savePseudonym = savePseudonym; + } + + @JsonGetter("kheopsAlbums") + @OneToMany(mappedBy = "destinationEntity", cascade = CascadeType.REMOVE) + @LazyCollection(LazyCollectionOption.FALSE) + public List getKheopsAlbumEntities() { + return kheopsAlbumEntities; + } + + @JsonSetter("kheopsAlbums") + public void setKheopsAlbumEntities(List kheopsAlbumEntities) { + this.kheopsAlbumEntities = kheopsAlbumEntities; + } + + @JsonGetter("project") + @ManyToOne + @JoinColumn(name = "project_id") + public ProjectEntity getProjectEntity() { + return projectEntity; + } + + @JsonSetter("project") + public void setProjectEntity(ProjectEntity projectEntity) { + this.projectEntity = projectEntity; + } + + public boolean isActivateNotification() { + return activateNotification; + } + + public void setActivateNotification(boolean activateNotification) { + this.activateNotification = activateNotification; + } + + public String getTransferSyntax() { + return transferSyntax; + } + + public void setTransferSyntax(String transferSyntax) { + this.transferSyntax = transferSyntax; + } + + public boolean isTranscodeOnlyUncompressed() { + return transcodeOnlyUncompressed; + } + + public void setTranscodeOnlyUncompressed(boolean transcodeOnlyUncompressed) { + this.transcodeOnlyUncompressed = transcodeOnlyUncompressed; + } + + public boolean isTransferInProgress() { + return transferInProgress; + } + + public void setTransferInProgress(boolean transferInProgress) { + this.transferInProgress = transferInProgress; + } + + public LocalDateTime getEmailLastCheck() { + return emailLastCheck; + } + + public void setEmailLastCheck(LocalDateTime emailLastCheck) { + this.emailLastCheck = emailLastCheck; + } + + public LocalDateTime getLastTransfer() { + return lastTransfer; + } + + public void setLastTransfer(LocalDateTime lastTransfer) { + this.lastTransfer = lastTransfer; + } + + /** + * Informs if this object matches with the filter as text. + * @param filterText the filter as text. + * @return true if this object matches with the filter as text; false otherwise. + */ + public boolean matchesFilter(String filterText) { + return contains(description, filterText) // + || contains(notify, filterText) // + || contains(notifyObjectErrorPrefix, filterText) // + || contains(notifyObjectPattern, filterText) // + || contains(notifyObjectValues, filterText) // + || contains(aeTitle, filterText) // + || contains(hostname, filterText) // + || equals(port, filterText) // + || contains(url, filterText) // + || contains(urlCredentials, filterText) // + || contains(headers, filterText); + } + + private boolean contains(String value, String filterText) { + return value != null && value.contains(filterText); + } + + private boolean equals(Integer value, String filterText) { + return value != null && value.toString().equals(filterText); + } + + @Override + public String toString() { + if (destinationType != null) { + switch (destinationType) { + case dicom: + return "Destination [id=" + id + ", description=" + description + ", type=" + destinationType + + ", notify=" + notify + ", notifyObjectErrorPrefix=" + notifyObjectErrorPrefix + + ", notifyObjectPattern=" + notifyObjectPattern + ", notifyObjectValues=" + notifyObjectValues + + ", notifyInterval=" + notifyInterval + ", aeTitle=" + aeTitle + ", hostname=" + hostname + + ", port=" + port + ", useaetdest=" + useaetdest + "]"; + case stow: + return "Destination [id=" + id + ", description=" + description + ", type=" + destinationType + + ", notify=" + notify + ", notifyObjectErrorPrefix=" + notifyObjectErrorPrefix + + ", notifyObjectPattern=" + notifyObjectPattern + ", notifyObjectValues=" + notifyObjectValues + + ", notifyInterval=" + notifyInterval + ", url=" + url + ", urlCredentials=" + urlCredentials + + ", headers=" + headers + "]"; + } + } + return "Destination [id=" + id + ", description=" + description + ", type=" + destinationType + ", notify=" + + notify + ", notifyObjectErrorPrefix=" + notifyObjectErrorPrefix + ", notifyObjectPattern=" + + notifyObjectPattern + ", notifyObjectValues=" + notifyObjectValues + ", notifyInterval=" + + notifyInterval + "]"; + } + + public String retrieveStringReference() { + if (destinationType != null) { + switch (destinationType) { + case dicom: + return getAeTitle(); + case stow: + return getUrl() + ":" + getPort(); + } + } + return "Type of destination is unknown"; + } + // + // @Override + // public boolean equals(Object o) { + // if (this == o) { + // return true; + // } + // if (o == null || getClass() != o.getClass()) { + // return false; + // } + // DestinationEntity that = (DestinationEntity) o; + // return desidentification == that.desidentification + // && issuerByDefault == that.issuerByDefault + // && filterBySOPClasses == that.filterBySOPClasses + // && Objects.equals(id, that.id) + // && Objects.equals(description, that.description) + // && destinationType == that.destinationType + // && pseudonymType == that.pseudonymType + // && Objects.equals(tag, that.tag) + // && Objects.equals(delimiter, that.delimiter) + // && Objects.equals(position, that.position) + // && Objects.equals(savePseudonym, that.savePseudonym) + // && Objects.equals(transferSyntax, that.transferSyntax) + // && Objects.equals(transcodeOnlyUncompressed, that.transcodeOnlyUncompressed) + // && Objects.equals(activateNotification, that.activateNotification) + // && Objects.equals(notify, that.notify) + // && Objects.equals(notifyObjectErrorPrefix, that.notifyObjectErrorPrefix) + // && Objects.equals(notifyObjectPattern, that.notifyObjectPattern) + // && Objects.equals(notifyObjectValues, that.notifyObjectValues) + // && Objects.equals(notifyInterval, that.notifyInterval) + // && Objects.equals(aeTitle, that.aeTitle) + // && Objects.equals(hostname, that.hostname) + // && Objects.equals(port, that.port) + // && Objects.equals(useaetdest, that.useaetdest) + // && Objects.equals(url, that.url) + // && Objects.equals(urlCredentials, that.urlCredentials) + // && Objects.equals(headers, that.headers); + // } + // + // @Override + // public int hashCode() { + // return Objects.hash( + // id, + // description, + // destinationType, + // desidentification, + // issuerByDefault, + // pseudonymType, + // tag, + // delimiter, + // position, + // savePseudonym, + // filterBySOPClasses, + // transferSyntax, + // transcodeOnlyUncompressed, + // activateNotification, + // notify, + // notifyObjectErrorPrefix, + // notifyObjectPattern, + // notifyObjectValues, + // notifyInterval, + // aeTitle, + // hostname, + // port, + // useaetdest, + // url, + // urlCredentials, + // headers); + // } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + DestinationEntity that = (DestinationEntity) o; + return Objects.equals(id, that.id); + } + + @Override + public int hashCode() { + return Objects.hash(id); + } + + public String toStringDicomNotificationDestination() { + return "Host=" + getHostname() + " AET=" + getAeTitle() + " Port=" + getPort(); + } + } diff --git a/src/main/java/org/karnak/backend/data/entity/DicomSourceNodeEntity.java b/src/main/java/org/karnak/backend/data/entity/DicomSourceNodeEntity.java index 333af93c1..8ec6bb1ae 100644 --- a/src/main/java/org/karnak/backend/data/entity/DicomSourceNodeEntity.java +++ b/src/main/java/org/karnak/backend/data/entity/DicomSourceNodeEntity.java @@ -25,135 +25,129 @@ @Table(name = "dicom_source_node") public class DicomSourceNodeEntity implements Serializable { - private static final long serialVersionUID = -4917273057619947934L; - - private Long id; - private String description; - // AETitle of the source node. - private String aeTitle; - // the host or IP of the source node. If the hostname exists then it is checked - // (allows a restriction on the host not only in the AETitle). - private String hostname; - // if "true" check the hostname during the DICOM association and if not match - // the connection is abort - private Boolean checkHostname; - private ForwardNodeEntity forwardNodeEntity; - - public DicomSourceNodeEntity() { - this.description = ""; - this.aeTitle = ""; - this.hostname = ""; - this.checkHostname = Boolean.FALSE; - } - - public static DicomSourceNodeEntity ofEmpty() { - DicomSourceNodeEntity instance = new DicomSourceNodeEntity(); - return instance; - } - - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - @NotBlank(message = "AETitle is mandatory") - @Size(max = 16, message = "AETitle has more than 16 characters") - public String getAeTitle() { - return aeTitle; - } - - public void setAeTitle(String aeTitle) { - this.aeTitle = aeTitle; - } - - public String getHostname() { - return hostname; - } - - public void setHostname(String hostname) { - this.hostname = hostname; - } - - @ManyToOne - @JoinColumn(name = "forward_node_id") - public ForwardNodeEntity getForwardNodeEntity() { - return forwardNodeEntity; - } - - public void setForwardNodeEntity(ForwardNodeEntity forwardNodeEntity) { - this.forwardNodeEntity = forwardNodeEntity; - } - - public Boolean getCheckHostname() { - return checkHostname; - } - - public void setCheckHostname(Boolean checkHostname) { - this.checkHostname = checkHostname; - } - - /** - * Informs if this object matches with the filter as text. - * - * @param filterText the filter as text. - * @return true if this object matches with the filter as text; false otherwise. - */ - public boolean matchesFilter(String filterText) { - return contains(description, filterText) // - || contains(aeTitle, filterText) // - || contains(hostname, filterText); - } - - private boolean contains(String value, String filterText) { - return value != null && value.contains(filterText); - } - - @Override - public String toString() { - return "DicomSourceNode [id=" - + id - + ", description=" - + description - + ", aeTitle=" - + aeTitle - + ", hostname=" - + hostname - + ", checkHostname=" - + checkHostname - + "]"; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - DicomSourceNodeEntity that = (DicomSourceNodeEntity) o; - return Objects.equals(id, that.id) - && Objects.equals(description, that.description) - && Objects.equals(aeTitle, that.aeTitle) - && Objects.equals(hostname, that.hostname) - && Objects.equals(checkHostname, that.checkHostname); - } - - @Override - public int hashCode() { - return Objects.hash(id, description, aeTitle, hostname, checkHostname); - } + private static final long serialVersionUID = -4917273057619947934L; + + private Long id; + + private String description; + + // AETitle of the source node. + private String aeTitle; + + // the host or IP of the source node. If the hostname exists then it is checked + // (allows a restriction on the host not only in the AETitle). + private String hostname; + + // if "true" check the hostname during the DICOM association and if not match + // the connection is abort + private Boolean checkHostname; + + private ForwardNodeEntity forwardNodeEntity; + + public DicomSourceNodeEntity() { + this.description = ""; + this.aeTitle = ""; + this.hostname = ""; + this.checkHostname = Boolean.FALSE; + } + + public static DicomSourceNodeEntity ofEmpty() { + DicomSourceNodeEntity instance = new DicomSourceNodeEntity(); + return instance; + } + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + @NotBlank(message = "AETitle is mandatory") + @Size(max = 16, message = "AETitle has more than 16 characters") + public String getAeTitle() { + return aeTitle; + } + + public void setAeTitle(String aeTitle) { + this.aeTitle = aeTitle; + } + + public String getHostname() { + return hostname; + } + + public void setHostname(String hostname) { + this.hostname = hostname; + } + + @ManyToOne + @JoinColumn(name = "forward_node_id") + public ForwardNodeEntity getForwardNodeEntity() { + return forwardNodeEntity; + } + + public void setForwardNodeEntity(ForwardNodeEntity forwardNodeEntity) { + this.forwardNodeEntity = forwardNodeEntity; + } + + public Boolean getCheckHostname() { + return checkHostname; + } + + public void setCheckHostname(Boolean checkHostname) { + this.checkHostname = checkHostname; + } + + /** + * Informs if this object matches with the filter as text. + * @param filterText the filter as text. + * @return true if this object matches with the filter as text; false otherwise. + */ + public boolean matchesFilter(String filterText) { + return contains(description, filterText) // + || contains(aeTitle, filterText) // + || contains(hostname, filterText); + } + + private boolean contains(String value, String filterText) { + return value != null && value.contains(filterText); + } + + @Override + public String toString() { + return "DicomSourceNode [id=" + id + ", description=" + description + ", aeTitle=" + aeTitle + ", hostname=" + + hostname + ", checkHostname=" + checkHostname + "]"; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + DicomSourceNodeEntity that = (DicomSourceNodeEntity) o; + return Objects.equals(id, that.id) && Objects.equals(description, that.description) + && Objects.equals(aeTitle, that.aeTitle) && Objects.equals(hostname, that.hostname) + && Objects.equals(checkHostname, that.checkHostname); + } + + @Override + public int hashCode() { + return Objects.hash(id, description, aeTitle, hostname, checkHostname); + } + } diff --git a/src/main/java/org/karnak/backend/data/entity/ExcludedTagEntity.java b/src/main/java/org/karnak/backend/data/entity/ExcludedTagEntity.java index e96da45cc..b91f1e625 100644 --- a/src/main/java/org/karnak/backend/data/entity/ExcludedTagEntity.java +++ b/src/main/java/org/karnak/backend/data/entity/ExcludedTagEntity.java @@ -17,11 +17,13 @@ @DiscriminatorValue("ExcludedTag") public class ExcludedTagEntity extends TagEntity implements Serializable { - private static final long serialVersionUID = -5068272710332856139L; + private static final long serialVersionUID = -5068272710332856139L; - public ExcludedTagEntity() {} + public ExcludedTagEntity() { + } + + public ExcludedTagEntity(String tagValue, ProfileElementEntity profileElementEntity) { + super(tagValue, profileElementEntity); + } - public ExcludedTagEntity(String tagValue, ProfileElementEntity profileElementEntity) { - super(tagValue, profileElementEntity); - } } diff --git a/src/main/java/org/karnak/backend/data/entity/ForwardNodeEntity.java b/src/main/java/org/karnak/backend/data/entity/ForwardNodeEntity.java index 516e03225..9c52b0148 100644 --- a/src/main/java/org/karnak/backend/data/entity/ForwardNodeEntity.java +++ b/src/main/java/org/karnak/backend/data/entity/ForwardNodeEntity.java @@ -28,178 +28,166 @@ @Table(name = "forward_node") public class ForwardNodeEntity implements Serializable { - private static final long serialVersionUID = 2095439136652046994L; - - private Long id; - private String fwdDescription; - // AETitle which defined a mapping of the gateway. This AETitle is configured as - // a destination in the DICOM component that sends images to the gateway. - private String fwdAeTitle; - // Specification of a DICOM source node (the one which sends images to the - // gateway). When no source node is defined all the DICOM nodes are accepted by - // the gateway. - private Set sourceNodes = new HashSet<>(); - // Specification of a final DICOM destination node. Multiple destinations can be - // defined either as a DICOM or DICOMWeb type. - private Set destinationEntities = new HashSet<>(); - - public ForwardNodeEntity() { - this.fwdAeTitle = ""; - this.fwdDescription = ""; - } - - public ForwardNodeEntity(String fwdAeTitle) { - this.fwdAeTitle = fwdAeTitle; - this.fwdDescription = ""; - } - - public static ForwardNodeEntity ofEmpty() { - return new ForwardNodeEntity(); - } - - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - @Column(name = "description") - public String getFwdDescription() { - return this.fwdDescription; - } - - public void setFwdDescription(String fwdDescription) { - this.fwdDescription = fwdDescription; - } - - @NotBlank(message = "Forward AETitle is mandatory") - @Size(max = 16, message = "Forward AETitle has more than 16 characters") - public String getFwdAeTitle() { - return this.fwdAeTitle; - } - - public void setFwdAeTitle(String fwdAeTitle) { - this.fwdAeTitle = fwdAeTitle; - } - - @OneToMany( - mappedBy = "forwardNodeEntity", - cascade = CascadeType.ALL, - fetch = FetchType.EAGER, - orphanRemoval = true) - public Set getSourceNodes() { - return this.sourceNodes; - } - - public void setSourceNodes(Set sourceNodes) { - this.sourceNodes = sourceNodes; - } - - public void addSourceNode(DicomSourceNodeEntity sourceNode) { - sourceNode.setForwardNodeEntity(this); - this.sourceNodes.add(sourceNode); - } - - public void removeSourceNode(DicomSourceNodeEntity sourceNode) { - this.sourceNodes.remove(sourceNode); - } - - @OneToMany( - mappedBy = "forwardNodeEntity", - cascade = CascadeType.ALL, - fetch = FetchType.EAGER, - orphanRemoval = true) - public Set getDestinationEntities() { - return destinationEntities; - } - - public void setDestinationEntities(Set destinationEntities) { - this.destinationEntities = destinationEntities; - } - - public void addDestination(DestinationEntity destinationEntity) { - destinationEntity.setForwardNodeEntity(this); - this.destinationEntities.add(destinationEntity); - } - - public void removeDestination(DestinationEntity destinationEntity) { - this.destinationEntities.remove(destinationEntity); - } - - /** - * Informs if this object matches with the filter as text. - * - * @param filterText the filter as text. - * @return true if this object matches with the filter as text; false otherwise. - */ - public boolean matchesFilter(String filterText) { - if (contains(fwdAeTitle, filterText) // - || contains(fwdDescription, filterText)) { - return true; - } - - for (DicomSourceNodeEntity sourceNode : sourceNodes) { - if (sourceNode.matchesFilter(filterText)) { - return true; - } - } - - for (DestinationEntity destinationEntity : destinationEntities) { - if (destinationEntity.matchesFilter(filterText)) { - return true; - } - } - - return false; - } - - private boolean contains(String value, String filterText) { - return value != null && value.contains(filterText); - } - - @Override - public String toString() { - return "ForwardNode [id=" - + id - + ", description=" - + fwdDescription - + ", fwdAeTitle=" - + fwdAeTitle - + ", sourceNodes=" - + sourceNodes - + ", destinations=" - + destinationEntities - + "]"; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((id == null) ? 0 : id.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - ForwardNodeEntity other = (ForwardNodeEntity) obj; - if (id == null) { - return other.id == null; - } else { - return id.equals(other.id); - } - } + private static final long serialVersionUID = 2095439136652046994L; + + private Long id; + + private String fwdDescription; + + // AETitle which defined a mapping of the gateway. This AETitle is configured as + // a destination in the DICOM component that sends images to the gateway. + private String fwdAeTitle; + + // Specification of a DICOM source node (the one which sends images to the + // gateway). When no source node is defined all the DICOM nodes are accepted by + // the gateway. + private Set sourceNodes = new HashSet<>(); + + // Specification of a final DICOM destination node. Multiple destinations can be + // defined either as a DICOM or DICOMWeb type. + private Set destinationEntities = new HashSet<>(); + + public ForwardNodeEntity() { + this.fwdAeTitle = ""; + this.fwdDescription = ""; + } + + public ForwardNodeEntity(String fwdAeTitle) { + this.fwdAeTitle = fwdAeTitle; + this.fwdDescription = ""; + } + + public static ForwardNodeEntity ofEmpty() { + return new ForwardNodeEntity(); + } + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + @Column(name = "description") + public String getFwdDescription() { + return this.fwdDescription; + } + + public void setFwdDescription(String fwdDescription) { + this.fwdDescription = fwdDescription; + } + + @NotBlank(message = "Forward AETitle is mandatory") + @Size(max = 16, message = "Forward AETitle has more than 16 characters") + public String getFwdAeTitle() { + return this.fwdAeTitle; + } + + public void setFwdAeTitle(String fwdAeTitle) { + this.fwdAeTitle = fwdAeTitle; + } + + @OneToMany(mappedBy = "forwardNodeEntity", cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true) + public Set getSourceNodes() { + return this.sourceNodes; + } + + public void setSourceNodes(Set sourceNodes) { + this.sourceNodes = sourceNodes; + } + + public void addSourceNode(DicomSourceNodeEntity sourceNode) { + sourceNode.setForwardNodeEntity(this); + this.sourceNodes.add(sourceNode); + } + + public void removeSourceNode(DicomSourceNodeEntity sourceNode) { + this.sourceNodes.remove(sourceNode); + } + + @OneToMany(mappedBy = "forwardNodeEntity", cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true) + public Set getDestinationEntities() { + return destinationEntities; + } + + public void setDestinationEntities(Set destinationEntities) { + this.destinationEntities = destinationEntities; + } + + public void addDestination(DestinationEntity destinationEntity) { + destinationEntity.setForwardNodeEntity(this); + this.destinationEntities.add(destinationEntity); + } + + public void removeDestination(DestinationEntity destinationEntity) { + this.destinationEntities.remove(destinationEntity); + } + + /** + * Informs if this object matches with the filter as text. + * @param filterText the filter as text. + * @return true if this object matches with the filter as text; false otherwise. + */ + public boolean matchesFilter(String filterText) { + if (contains(fwdAeTitle, filterText) // + || contains(fwdDescription, filterText)) { + return true; + } + + for (DicomSourceNodeEntity sourceNode : sourceNodes) { + if (sourceNode.matchesFilter(filterText)) { + return true; + } + } + + for (DestinationEntity destinationEntity : destinationEntities) { + if (destinationEntity.matchesFilter(filterText)) { + return true; + } + } + + return false; + } + + private boolean contains(String value, String filterText) { + return value != null && value.contains(filterText); + } + + @Override + public String toString() { + return "ForwardNode [id=" + id + ", description=" + fwdDescription + ", fwdAeTitle=" + fwdAeTitle + + ", sourceNodes=" + sourceNodes + ", destinations=" + destinationEntities + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((id == null) ? 0 : id.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + ForwardNodeEntity other = (ForwardNodeEntity) obj; + if (id == null) { + return other.id == null; + } + else { + return id.equals(other.id); + } + } + } diff --git a/src/main/java/org/karnak/backend/data/entity/IncludedTagEntity.java b/src/main/java/org/karnak/backend/data/entity/IncludedTagEntity.java index 845097709..570e4d4fc 100644 --- a/src/main/java/org/karnak/backend/data/entity/IncludedTagEntity.java +++ b/src/main/java/org/karnak/backend/data/entity/IncludedTagEntity.java @@ -17,11 +17,13 @@ @DiscriminatorValue("IncludedTag") public class IncludedTagEntity extends TagEntity implements Serializable { - private static final long serialVersionUID = 6644786515302502293L; + private static final long serialVersionUID = 6644786515302502293L; - public IncludedTagEntity() {} + public IncludedTagEntity() { + } + + public IncludedTagEntity(String tagValue, ProfileElementEntity profileElementEntity) { + super(tagValue, profileElementEntity); + } - public IncludedTagEntity(String tagValue, ProfileElementEntity profileElementEntity) { - super(tagValue, profileElementEntity); - } } diff --git a/src/main/java/org/karnak/backend/data/entity/KheopsAlbumsEntity.java b/src/main/java/org/karnak/backend/data/entity/KheopsAlbumsEntity.java index fbefaade7..98a540536 100644 --- a/src/main/java/org/karnak/backend/data/entity/KheopsAlbumsEntity.java +++ b/src/main/java/org/karnak/backend/data/entity/KheopsAlbumsEntity.java @@ -23,119 +23,108 @@ @Table(name = "kheops_albums") public class KheopsAlbumsEntity implements Serializable { - private static final long serialVersionUID = -3315720301354286325L; - - private Long id; - private String urlAPI; - private String authorizationDestination; - private String authorizationSource; - private String condition; - private DestinationEntity destinationEntity = new DestinationEntity(); - - public KheopsAlbumsEntity() {} - - public KheopsAlbumsEntity( - String urlAPI, - String authorizationDestination, - String authorizationSource, - String condition) { - this.urlAPI = urlAPI; - this.authorizationDestination = authorizationDestination; - this.authorizationSource = authorizationSource; - this.condition = condition; - } - - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public String getUrlAPI() { - return urlAPI; - } - - public void setUrlAPI(String urlAPI) { - this.urlAPI = urlAPI; - } - - public String getAuthorizationDestination() { - return authorizationDestination; - } - - public void setAuthorizationDestination(String authorizationDestination) { - this.authorizationDestination = authorizationDestination; - } - - public String getAuthorizationSource() { - return authorizationSource; - } - - public void setAuthorizationSource(String authorizationSource) { - this.authorizationSource = authorizationSource; - } - - public String getCondition() { - return condition; - } - - public void setCondition(String condition) { - this.condition = condition; - } - - @ManyToOne - @JoinColumn(name = "destination_id") - public DestinationEntity getDestinationEntity() { - return destinationEntity; - } - - public void setDestinationEntity(DestinationEntity destinationEntity) { - this.destinationEntity = destinationEntity; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - KheopsAlbumsEntity that = (KheopsAlbumsEntity) o; - return Objects.equals(urlAPI, that.urlAPI) - && Objects.equals(authorizationDestination, that.authorizationDestination) - && Objects.equals(authorizationSource, that.authorizationSource) - && Objects.equals(condition, that.condition); - } - - @Override - public int hashCode() { - return Objects.hash(urlAPI, authorizationDestination, authorizationSource, condition); - } - - @Override - public String toString() { - return "KheopsAlbumsEntity{" - + "id=" - + id - + ", urlAPI='" - + urlAPI - + '\'' - + ", authorizationDestination='" - + authorizationDestination - + '\'' - + ", authorizationSource='" - + authorizationSource - + '\'' - + ", condition='" - + condition - + '\'' - + ", destinationEntity=" - + destinationEntity - + '}'; - } + private static final long serialVersionUID = -3315720301354286325L; + + private Long id; + + private String urlAPI; + + private String authorizationDestination; + + private String authorizationSource; + + private String condition; + + private DestinationEntity destinationEntity = new DestinationEntity(); + + public KheopsAlbumsEntity() { + } + + public KheopsAlbumsEntity(String urlAPI, String authorizationDestination, String authorizationSource, + String condition) { + this.urlAPI = urlAPI; + this.authorizationDestination = authorizationDestination; + this.authorizationSource = authorizationSource; + this.condition = condition; + } + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getUrlAPI() { + return urlAPI; + } + + public void setUrlAPI(String urlAPI) { + this.urlAPI = urlAPI; + } + + public String getAuthorizationDestination() { + return authorizationDestination; + } + + public void setAuthorizationDestination(String authorizationDestination) { + this.authorizationDestination = authorizationDestination; + } + + public String getAuthorizationSource() { + return authorizationSource; + } + + public void setAuthorizationSource(String authorizationSource) { + this.authorizationSource = authorizationSource; + } + + public String getCondition() { + return condition; + } + + public void setCondition(String condition) { + this.condition = condition; + } + + @ManyToOne + @JoinColumn(name = "destination_id") + public DestinationEntity getDestinationEntity() { + return destinationEntity; + } + + public void setDestinationEntity(DestinationEntity destinationEntity) { + this.destinationEntity = destinationEntity; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + KheopsAlbumsEntity that = (KheopsAlbumsEntity) o; + return Objects.equals(urlAPI, that.urlAPI) + && Objects.equals(authorizationDestination, that.authorizationDestination) + && Objects.equals(authorizationSource, that.authorizationSource) + && Objects.equals(condition, that.condition); + } + + @Override + public int hashCode() { + return Objects.hash(urlAPI, authorizationDestination, authorizationSource, condition); + } + + @Override + public String toString() { + return "KheopsAlbumsEntity{" + "id=" + id + ", urlAPI='" + urlAPI + '\'' + ", authorizationDestination='" + + authorizationDestination + '\'' + ", authorizationSource='" + authorizationSource + '\'' + + ", condition='" + condition + '\'' + ", destinationEntity=" + destinationEntity + '}'; + } + } diff --git a/src/main/java/org/karnak/backend/data/entity/MaskEntity.java b/src/main/java/org/karnak/backend/data/entity/MaskEntity.java index acbebea11..9c3e3414c 100644 --- a/src/main/java/org/karnak/backend/data/entity/MaskEntity.java +++ b/src/main/java/org/karnak/backend/data/entity/MaskEntity.java @@ -31,98 +31,102 @@ @Table(name = "masks") public class MaskEntity implements Serializable { - private static final long serialVersionUID = 1833858684629178458L; - - private Long id; - private ProfileEntity profileEntity; - private String stationName; - private String color; - private List rectangles = new ArrayList<>(); - - public MaskEntity() {} - - public MaskEntity(String stationName, String color, ProfileEntity profileEntity) { - this.stationName = stationName; - this.color = color; - this.profileEntity = profileEntity; - } - - public void addRectangle(String rectangle) { - Rectangle rect = RectangleListConverter.stringToRectangle(rectangle); - if (rect != null) { - rectangles.add(rect); - } - } - - public void addRectangle(Rectangle rect) { - rectangles.add(rect); - } - - @Convert(converter = RectangleListConverter.class) - @JsonSerialize(converter = RectangleListToStringListConverter.class) - public List getRectangles() { - return rectangles; - } - - public void setRectangles(List rectangles) { - this.rectangles = rectangles; - } - - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - @JsonIgnore - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - @ManyToOne - @JoinColumn(name = "profile_id", nullable = false) - @JsonIgnore - public ProfileEntity getProfileEntity() { - return profileEntity; - } - - public void setProfileEntity(ProfileEntity profileEntity) { - this.profileEntity = profileEntity; - } - - public String getStationName() { - return stationName; - } - - public void setStationName(String stationName) { - this.stationName = stationName; - } - - public String getColor() { - return color; - } - - public void setColor(String color) { - this.color = color; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - MaskEntity that = (MaskEntity) o; - return Objects.equals(id, that.id) - && Objects.equals(stationName, that.stationName) - && Objects.equals(color, that.color) - && Objects.equals(rectangles, that.rectangles); - } - - @Override - public int hashCode() { - return Objects.hash(id, stationName, color, rectangles); - } + private static final long serialVersionUID = 1833858684629178458L; + + private Long id; + + private ProfileEntity profileEntity; + + private String stationName; + + private String color; + + private List rectangles = new ArrayList<>(); + + public MaskEntity() { + } + + public MaskEntity(String stationName, String color, ProfileEntity profileEntity) { + this.stationName = stationName; + this.color = color; + this.profileEntity = profileEntity; + } + + public void addRectangle(String rectangle) { + Rectangle rect = RectangleListConverter.stringToRectangle(rectangle); + if (rect != null) { + rectangles.add(rect); + } + } + + public void addRectangle(Rectangle rect) { + rectangles.add(rect); + } + + @Convert(converter = RectangleListConverter.class) + @JsonSerialize(converter = RectangleListToStringListConverter.class) + public List getRectangles() { + return rectangles; + } + + public void setRectangles(List rectangles) { + this.rectangles = rectangles; + } + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + @JsonIgnore + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + @ManyToOne + @JoinColumn(name = "profile_id", nullable = false) + @JsonIgnore + public ProfileEntity getProfileEntity() { + return profileEntity; + } + + public void setProfileEntity(ProfileEntity profileEntity) { + this.profileEntity = profileEntity; + } + + public String getStationName() { + return stationName; + } + + public void setStationName(String stationName) { + this.stationName = stationName; + } + + public String getColor() { + return color; + } + + public void setColor(String color) { + this.color = color; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + MaskEntity that = (MaskEntity) o; + return Objects.equals(id, that.id) && Objects.equals(stationName, that.stationName) + && Objects.equals(color, that.color) && Objects.equals(rectangles, that.rectangles); + } + + @Override + public int hashCode() { + return Objects.hash(id, stationName, color, rectangles); + } + } diff --git a/src/main/java/org/karnak/backend/data/entity/ProfileElementEntity.java b/src/main/java/org/karnak/backend/data/entity/ProfileElementEntity.java index e6bbc916c..041f9277c 100644 --- a/src/main/java/org/karnak/backend/data/entity/ProfileElementEntity.java +++ b/src/main/java/org/karnak/backend/data/entity/ProfileElementEntity.java @@ -38,198 +38,193 @@ @JsonInclude(JsonInclude.Include.NON_EMPTY) public class ProfileElementEntity implements Serializable { - private static final long serialVersionUID = 818925943276758147L; - - private Long id; - private String name; - private String codename; - private String condition; - private String action; - private String option; - private Integer position; - private ProfileEntity profileEntity; - private List includedTagEntities = new ArrayList<>(); - private List excludedTagEntities = new ArrayList<>(); - private List argumentEntities = new ArrayList<>(); - - public ProfileElementEntity() {} - - public ProfileElementEntity( - String name, - String codename, - String condition, - String action, - String option, - Integer position, - ProfileEntity profileEntity) { - this.name = name; - this.codename = codename; - this.condition = condition; - this.action = action; - this.option = option; - this.position = position; - this.profileEntity = profileEntity; - } - - public ProfileElementEntity( - String name, - String codename, - String condition, - String action, - String option, - List argumentEntities, - Integer position, - ProfileEntity profileEntity) { - this.name = name; - this.codename = codename; - this.condition = condition; - this.action = action; - this.option = option; - this.argumentEntities = argumentEntities; - this.position = position; - this.profileEntity = profileEntity; - } - - public void addIncludedTag(IncludedTagEntity includedtag) { - this.includedTagEntities.add(includedtag); - } - - public void addExceptedtags(ExcludedTagEntity exceptedtags) { - this.excludedTagEntities.add(exceptedtags); - } - - public void addArgument(ArgumentEntity argumentEntity) { - this.argumentEntities.add(argumentEntity); - } - - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - @JsonIgnore - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getCodename() { - return codename; - } - - public void setCodename(String codename) { - this.codename = codename; - } - - public String getCondition() { - return condition; - } - - public void setCondition(String condition) { - this.condition = condition; - } - - public String getAction() { - return action; - } - - public void setAction(String action) { - this.action = action; - } - - public String getOption() { - return option; - } - - public void setOption(String option) { - this.option = option; - } - - @JsonGetter("arguments") - @OneToMany(mappedBy = "profileElementEntity", cascade = CascadeType.ALL) - @LazyCollection(LazyCollectionOption.FALSE) - @JsonSerialize(converter = ArgumentToMapConverter.class) - public List getArgumentEntities() { - return argumentEntities; - } - - @JsonSetter("arguments") - public void setArgumentEntities(List argumentEntities) { - this.argumentEntities = argumentEntities; - } - - @JsonIgnore - public Integer getPosition() { - return position; - } - - public void setPosition(Integer position) { - this.position = position; - } - - @ManyToOne() - @JoinColumn(name = "profile_id", nullable = false) - @JsonIgnore - public ProfileEntity getProfileEntity() { - return profileEntity; - } - - public void setProfileEntity(ProfileEntity profileEntity) { - this.profileEntity = profileEntity; - } - - @JsonGetter("tags") - @OneToMany(mappedBy = "profileElementEntity", cascade = CascadeType.ALL, fetch = FetchType.EAGER) - @JsonSerialize(converter = TagListToStringListConverter.class) - public List getIncludedTagEntities() { - return includedTagEntities; - } - - @JsonSetter("tags") - public void setIncludedTagEntities(List includedTagEntities) { - this.includedTagEntities = includedTagEntities; - } - - @JsonGetter("excludedTags") - @OneToMany(mappedBy = "profileElementEntity", cascade = CascadeType.ALL, fetch = FetchType.EAGER) - @JsonSerialize(converter = TagListToStringListConverter.class) - public List getExcludedTagEntities() { - return excludedTagEntities; - } - - @JsonSetter("excludedTags") - public void setExcludedTagEntities(List excludedTagEntities) { - this.excludedTagEntities = excludedTagEntities; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - ProfileElementEntity that = (ProfileElementEntity) o; - return Objects.equals(id, that.id) - && Objects.equals(name, that.name) - && Objects.equals(codename, that.codename) - && Objects.equals(condition, that.condition) - && Objects.equals(action, that.action) - && Objects.equals(option, that.option) - && Objects.equals(position, that.position); - } - - @Override - public int hashCode() { - return Objects.hash(id, name, codename, condition, action, option, position); - } + private static final long serialVersionUID = 818925943276758147L; + + private Long id; + + private String name; + + private String codename; + + private String condition; + + private String action; + + private String option; + + private Integer position; + + private ProfileEntity profileEntity; + + private List includedTagEntities = new ArrayList<>(); + + private List excludedTagEntities = new ArrayList<>(); + + private List argumentEntities = new ArrayList<>(); + + public ProfileElementEntity() { + } + + public ProfileElementEntity(String name, String codename, String condition, String action, String option, + Integer position, ProfileEntity profileEntity) { + this.name = name; + this.codename = codename; + this.condition = condition; + this.action = action; + this.option = option; + this.position = position; + this.profileEntity = profileEntity; + } + + public ProfileElementEntity(String name, String codename, String condition, String action, String option, + List argumentEntities, Integer position, ProfileEntity profileEntity) { + this.name = name; + this.codename = codename; + this.condition = condition; + this.action = action; + this.option = option; + this.argumentEntities = argumentEntities; + this.position = position; + this.profileEntity = profileEntity; + } + + public void addIncludedTag(IncludedTagEntity includedtag) { + this.includedTagEntities.add(includedtag); + } + + public void addExceptedtags(ExcludedTagEntity exceptedtags) { + this.excludedTagEntities.add(exceptedtags); + } + + public void addArgument(ArgumentEntity argumentEntity) { + this.argumentEntities.add(argumentEntity); + } + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + @JsonIgnore + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getCodename() { + return codename; + } + + public void setCodename(String codename) { + this.codename = codename; + } + + public String getCondition() { + return condition; + } + + public void setCondition(String condition) { + this.condition = condition; + } + + public String getAction() { + return action; + } + + public void setAction(String action) { + this.action = action; + } + + public String getOption() { + return option; + } + + public void setOption(String option) { + this.option = option; + } + + @JsonGetter("arguments") + @OneToMany(mappedBy = "profileElementEntity", cascade = CascadeType.ALL) + @LazyCollection(LazyCollectionOption.FALSE) + @JsonSerialize(converter = ArgumentToMapConverter.class) + public List getArgumentEntities() { + return argumentEntities; + } + + @JsonSetter("arguments") + public void setArgumentEntities(List argumentEntities) { + this.argumentEntities = argumentEntities; + } + + @JsonIgnore + public Integer getPosition() { + return position; + } + + public void setPosition(Integer position) { + this.position = position; + } + + @ManyToOne() + @JoinColumn(name = "profile_id", nullable = false) + @JsonIgnore + public ProfileEntity getProfileEntity() { + return profileEntity; + } + + public void setProfileEntity(ProfileEntity profileEntity) { + this.profileEntity = profileEntity; + } + + @JsonGetter("tags") + @OneToMany(mappedBy = "profileElementEntity", cascade = CascadeType.ALL, fetch = FetchType.EAGER) + @JsonSerialize(converter = TagListToStringListConverter.class) + public List getIncludedTagEntities() { + return includedTagEntities; + } + + @JsonSetter("tags") + public void setIncludedTagEntities(List includedTagEntities) { + this.includedTagEntities = includedTagEntities; + } + + @JsonGetter("excludedTags") + @OneToMany(mappedBy = "profileElementEntity", cascade = CascadeType.ALL, fetch = FetchType.EAGER) + @JsonSerialize(converter = TagListToStringListConverter.class) + public List getExcludedTagEntities() { + return excludedTagEntities; + } + + @JsonSetter("excludedTags") + public void setExcludedTagEntities(List excludedTagEntities) { + this.excludedTagEntities = excludedTagEntities; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ProfileElementEntity that = (ProfileElementEntity) o; + return Objects.equals(id, that.id) && Objects.equals(name, that.name) && Objects.equals(codename, that.codename) + && Objects.equals(condition, that.condition) && Objects.equals(action, that.action) + && Objects.equals(option, that.option) && Objects.equals(position, that.position); + } + + @Override + public int hashCode() { + return Objects.hash(id, name, codename, condition, action, option, position); + } + } diff --git a/src/main/java/org/karnak/backend/data/entity/ProfileEntity.java b/src/main/java/org/karnak/backend/data/entity/ProfileEntity.java index 45b0073bf..4f1be4857 100644 --- a/src/main/java/org/karnak/backend/data/entity/ProfileEntity.java +++ b/src/main/java/org/karnak/backend/data/entity/ProfileEntity.java @@ -35,171 +35,168 @@ @Entity(name = "Profile") @Table(name = "profile") @JsonInclude(JsonInclude.Include.NON_EMPTY) -@JsonPropertyOrder({ - "name", - "version", - "minimumKarnakVersion", - "defaultIssuerOfPatientID", - "profileElementEntities", - "maskEntities" -}) +@JsonPropertyOrder({ "name", "version", "minimumKarnakVersion", "defaultIssuerOfPatientID", "profileElementEntities", + "maskEntities" }) public class ProfileEntity implements Serializable { - private static final long serialVersionUID = -7178858361090900170L; - - private Long id; - private String name; - private String version; - private String minimumKarnakVersion; - private String defaultIssuerOfPatientId; // not use in db but used in warning msg profile - private Boolean byDefault; - private Set profileElementEntities = new HashSet<>(); - private Set maskEntities = new HashSet<>(); - private List projectEntities; - - public ProfileEntity() {} - - public ProfileEntity( - String name, String version, String minimumKarnakVersion, String defaultIssuerOfPatientId) { - this.name = name; - this.version = version; - this.minimumKarnakVersion = minimumKarnakVersion; - this.defaultIssuerOfPatientId = defaultIssuerOfPatientId; - this.byDefault = false; - } - - public ProfileEntity( - String name, - String version, - String minimumKarnakVersion, - String defaultIssuerOfPatientId, - Boolean byDefault) { - this.name = name; - this.version = version; - this.minimumKarnakVersion = minimumKarnakVersion; - this.defaultIssuerOfPatientId = defaultIssuerOfPatientId; - this.byDefault = byDefault; - } - - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - @JsonIgnore - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public void addProfilePipe(ProfileElementEntity profileElementEntity) { - this.profileElementEntities.add(profileElementEntity); - } - - public void addMask(MaskEntity maskEntity) { - this.maskEntities.add(maskEntity); - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getVersion() { - return version; - } - - public void setVersion(String version) { - this.version = version; - } - - @JsonGetter("minimumKarnakVersion") - public String getMinimumKarnakVersion() { - return minimumKarnakVersion; - } - - @JsonSetter("minimumKarnakVersion") - public void setMinimumKarnakVersion(String minimumKarnakVersion) { - this.minimumKarnakVersion = minimumKarnakVersion; - } - - @JsonGetter("defaultIssuerOfPatientID") - @Transient // not use in db but used in warning msg profile - public String getDefaultIssuerOfPatientId() { - return defaultIssuerOfPatientId; - } - - @JsonSetter("defaultIssuerOfPatientID") - public void setDefaultIssuerOfPatientId(String defaultIssuerOfPatientId) { - this.defaultIssuerOfPatientId = defaultIssuerOfPatientId; - } - - @JsonGetter("profileElements") - @OneToMany(mappedBy = "profileEntity", cascade = CascadeType.ALL, fetch = FetchType.EAGER) - public Set getProfileElementEntities() { - return profileElementEntities; - } - - @JsonSetter("profileElements") - public void setProfileElementEntities(Set profileElementEntities) { - this.profileElementEntities = profileElementEntities; - } - - @JsonIgnore - @Column(name = "bydefault") - public Boolean getByDefault() { - return byDefault; - } - - public void setByDefault(Boolean bydefault) { - this.byDefault = bydefault; - } - - @JsonGetter("masks") - @OneToMany(mappedBy = "profileEntity", cascade = CascadeType.ALL, fetch = FetchType.EAGER) - public Set getMaskEntities() { - return maskEntities; - } - - @JsonSetter("masks") - public void setMaskEntities(Set maskEntities) { - this.maskEntities = maskEntities; - } - - @OneToMany(mappedBy = "profileEntity") - @LazyCollection(LazyCollectionOption.FALSE) - @JsonIgnore - public List getProjectEntities() { - return projectEntities; - } - - public void setProjectEntities(List projectEntities) { - this.projectEntities = projectEntities; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - ProfileEntity that = (ProfileEntity) o; - return Objects.equals(id, that.id) - && Objects.equals(name, that.name) - && Objects.equals(version, that.version) - && Objects.equals(minimumKarnakVersion, that.minimumKarnakVersion) - && Objects.equals(defaultIssuerOfPatientId, that.defaultIssuerOfPatientId) - && Objects.equals(byDefault, that.byDefault); - } - - @Override - public int hashCode() { - return Objects.hash( - id, name, version, minimumKarnakVersion, defaultIssuerOfPatientId, byDefault); - } + private static final long serialVersionUID = -7178858361090900170L; + + private Long id; + + private String name; + + private String version; + + private String minimumKarnakVersion; + + private String defaultIssuerOfPatientId; // not use in db but used in warning msg + // profile + + private Boolean byDefault; + + private Set profileElementEntities = new HashSet<>(); + + private Set maskEntities = new HashSet<>(); + + private List projectEntities; + + public ProfileEntity() { + } + + public ProfileEntity(String name, String version, String minimumKarnakVersion, String defaultIssuerOfPatientId) { + this.name = name; + this.version = version; + this.minimumKarnakVersion = minimumKarnakVersion; + this.defaultIssuerOfPatientId = defaultIssuerOfPatientId; + this.byDefault = false; + } + + public ProfileEntity(String name, String version, String minimumKarnakVersion, String defaultIssuerOfPatientId, + Boolean byDefault) { + this.name = name; + this.version = version; + this.minimumKarnakVersion = minimumKarnakVersion; + this.defaultIssuerOfPatientId = defaultIssuerOfPatientId; + this.byDefault = byDefault; + } + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + @JsonIgnore + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public void addProfilePipe(ProfileElementEntity profileElementEntity) { + this.profileElementEntities.add(profileElementEntity); + } + + public void addMask(MaskEntity maskEntity) { + this.maskEntities.add(maskEntity); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + @JsonGetter("minimumKarnakVersion") + public String getMinimumKarnakVersion() { + return minimumKarnakVersion; + } + + @JsonSetter("minimumKarnakVersion") + public void setMinimumKarnakVersion(String minimumKarnakVersion) { + this.minimumKarnakVersion = minimumKarnakVersion; + } + + @JsonGetter("defaultIssuerOfPatientID") + @Transient // not use in db but used in warning msg profile + public String getDefaultIssuerOfPatientId() { + return defaultIssuerOfPatientId; + } + + @JsonSetter("defaultIssuerOfPatientID") + public void setDefaultIssuerOfPatientId(String defaultIssuerOfPatientId) { + this.defaultIssuerOfPatientId = defaultIssuerOfPatientId; + } + + @JsonGetter("profileElements") + @OneToMany(mappedBy = "profileEntity", cascade = CascadeType.ALL, fetch = FetchType.EAGER) + public Set getProfileElementEntities() { + return profileElementEntities; + } + + @JsonSetter("profileElements") + public void setProfileElementEntities(Set profileElementEntities) { + this.profileElementEntities = profileElementEntities; + } + + @JsonIgnore + @Column(name = "bydefault") + public Boolean getByDefault() { + return byDefault; + } + + public void setByDefault(Boolean bydefault) { + this.byDefault = bydefault; + } + + @JsonGetter("masks") + @OneToMany(mappedBy = "profileEntity", cascade = CascadeType.ALL, fetch = FetchType.EAGER) + public Set getMaskEntities() { + return maskEntities; + } + + @JsonSetter("masks") + public void setMaskEntities(Set maskEntities) { + this.maskEntities = maskEntities; + } + + @OneToMany(mappedBy = "profileEntity") + @LazyCollection(LazyCollectionOption.FALSE) + @JsonIgnore + public List getProjectEntities() { + return projectEntities; + } + + public void setProjectEntities(List projectEntities) { + this.projectEntities = projectEntities; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ProfileEntity that = (ProfileEntity) o; + return Objects.equals(id, that.id) && Objects.equals(name, that.name) && Objects.equals(version, that.version) + && Objects.equals(minimumKarnakVersion, that.minimumKarnakVersion) + && Objects.equals(defaultIssuerOfPatientId, that.defaultIssuerOfPatientId) + && Objects.equals(byDefault, that.byDefault); + } + + @Override + public int hashCode() { + return Objects.hash(id, name, version, minimumKarnakVersion, defaultIssuerOfPatientId, byDefault); + } + } diff --git a/src/main/java/org/karnak/backend/data/entity/ProjectEntity.java b/src/main/java/org/karnak/backend/data/entity/ProjectEntity.java index 3817f1b86..6f7c522bf 100644 --- a/src/main/java/org/karnak/backend/data/entity/ProjectEntity.java +++ b/src/main/java/org/karnak/backend/data/entity/ProjectEntity.java @@ -31,128 +31,125 @@ @Table(name = "project") public class ProjectEntity implements Serializable { - private static final long serialVersionUID = 8809562914582842501L; - - private Long id; - private String name; - private List secretEntities; - private List destinationEntities; - private ProfileEntity profileEntity; - - public ProjectEntity() { - this.destinationEntities = new ArrayList<>(); - this.secretEntities = new ArrayList<>(); - } - - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - @OneToMany(mappedBy = "projectEntity", cascade = CascadeType.ALL) - @LazyCollection(LazyCollectionOption.FALSE) - public List getSecretEntities() { - return secretEntities; - } - - public void setSecretEntities(List secretEntities) { - this.secretEntities = secretEntities; - } - - @OneToMany(mappedBy = "projectEntity") - @LazyCollection(LazyCollectionOption.FALSE) - public List getDestinationEntities() { - return destinationEntities; - } - - public void setDestinationEntities(List destinationEntities) { - this.destinationEntities = destinationEntities; - } - - @ManyToOne - @JoinColumn(name = "profile_pipe_id") - public ProfileEntity getProfileEntity() { - return profileEntity; - } - - public void setProfileEntity(ProfileEntity profileEntity) { - this.profileEntity = profileEntity; - } - - /** - * Retrieve the active secret of the project - * - * @return active secret to be used - */ - public SecretEntity retrieveActiveSecret() { - return secretEntities.stream().filter(SecretEntity::isActive).findFirst().orElse(null); - } - - /** - * Set the secret in parameter in the list of secret of the project and activate it - * - * @param secretEntity Secret to add - */ - public void addActiveSecretEntity(SecretEntity secretEntity) { - applyActiveSecret(secretEntity); - secretEntities.add(secretEntity); - } - - /** - * Activate the secret in parameter and deactivate others - * - * @param secretEntity Secret to activate - */ - public void applyActiveSecret(SecretEntity secretEntity) { - secretEntities.forEach(s -> s.setActive(false)); - secretEntity.setActive(true); - } - - /** - * Build a label for the combobox secret - * - * @param secretEntity Label is build for this secretEntity - * @return Label built - */ - public static String buildLabelSecret(SecretEntity secretEntity) { - return "%s [created: %s]" - .formatted( - HMAC.showHexKey(HMAC.byteToHex(secretEntity.getKey())), - DateFormat.format( - secretEntity.getCreationDate(), DateFormat.FORMAT_DDMMYYYY_SLASH_HHMMSS_2POINTS)); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - ProjectEntity that = (ProjectEntity) o; - return Objects.equals(id, that.id) - && Objects.equals(name, that.name) - && Objects.equals(secretEntities, that.secretEntities) - && Objects.equals(destinationEntities, that.destinationEntities) - && Objects.equals(profileEntity, that.profileEntity); - } - - @Override - public int hashCode() { - return Objects.hash(id, name, secretEntities, destinationEntities, profileEntity); - } + private static final long serialVersionUID = 8809562914582842501L; + + private Long id; + + private String name; + + private List secretEntities; + + private List destinationEntities; + + private ProfileEntity profileEntity; + + public ProjectEntity() { + this.destinationEntities = new ArrayList<>(); + this.secretEntities = new ArrayList<>(); + } + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @OneToMany(mappedBy = "projectEntity", cascade = CascadeType.ALL) + @LazyCollection(LazyCollectionOption.FALSE) + public List getSecretEntities() { + return secretEntities; + } + + public void setSecretEntities(List secretEntities) { + this.secretEntities = secretEntities; + } + + @OneToMany(mappedBy = "projectEntity") + @LazyCollection(LazyCollectionOption.FALSE) + public List getDestinationEntities() { + return destinationEntities; + } + + public void setDestinationEntities(List destinationEntities) { + this.destinationEntities = destinationEntities; + } + + @ManyToOne + @JoinColumn(name = "profile_pipe_id") + public ProfileEntity getProfileEntity() { + return profileEntity; + } + + public void setProfileEntity(ProfileEntity profileEntity) { + this.profileEntity = profileEntity; + } + + /** + * Retrieve the active secret of the project + * @return active secret to be used + */ + public SecretEntity retrieveActiveSecret() { + return secretEntities.stream().filter(SecretEntity::isActive).findFirst().orElse(null); + } + + /** + * Set the secret in parameter in the list of secret of the project and activate it + * @param secretEntity Secret to add + */ + public void addActiveSecretEntity(SecretEntity secretEntity) { + applyActiveSecret(secretEntity); + secretEntities.add(secretEntity); + } + + /** + * Activate the secret in parameter and deactivate others + * @param secretEntity Secret to activate + */ + public void applyActiveSecret(SecretEntity secretEntity) { + secretEntities.forEach(s -> s.setActive(false)); + secretEntity.setActive(true); + } + + /** + * Build a label for the combobox secret + * @param secretEntity Label is build for this secretEntity + * @return Label built + */ + public static String buildLabelSecret(SecretEntity secretEntity) { + return "%s [created: %s]".formatted(HMAC.showHexKey(HMAC.byteToHex(secretEntity.getKey())), + DateFormat.format(secretEntity.getCreationDate(), DateFormat.FORMAT_DDMMYYYY_SLASH_HHMMSS_2POINTS)); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ProjectEntity that = (ProjectEntity) o; + return Objects.equals(id, that.id) && Objects.equals(name, that.name) + && Objects.equals(secretEntities, that.secretEntities) + && Objects.equals(destinationEntities, that.destinationEntities) + && Objects.equals(profileEntity, that.profileEntity); + } + + @Override + public int hashCode() { + return Objects.hash(id, name, secretEntities, destinationEntities, profileEntity); + } + } diff --git a/src/main/java/org/karnak/backend/data/entity/SOPClassUIDEntity.java b/src/main/java/org/karnak/backend/data/entity/SOPClassUIDEntity.java index 8b3c99584..3edc9a840 100644 --- a/src/main/java/org/karnak/backend/data/entity/SOPClassUIDEntity.java +++ b/src/main/java/org/karnak/backend/data/entity/SOPClassUIDEntity.java @@ -21,76 +21,79 @@ @Table(name = "sop_class_uid") public class SOPClassUIDEntity implements Serializable { - private static final long serialVersionUID = 2885426916053925842L; - - private Long id; - private String ciod; - private String uid; - private String name; - - public SOPClassUIDEntity() {} - - public SOPClassUIDEntity(String ciod, String uid, String name) { - this.ciod = ciod; - this.uid = uid; - this.name = name; - } - - public SOPClassUIDEntity(String ciod) { - this.ciod = ciod; - } - - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public String getCiod() { - return ciod; - } - - public void setCiod(String ciod) { - this.ciod = ciod; - } - - public String getUid() { - return uid; - } - - public void setUid(String uid) { - this.uid = uid; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - SOPClassUIDEntity that = (SOPClassUIDEntity) o; - return Objects.equals(id, that.id) - && Objects.equals(ciod, that.ciod) - && Objects.equals(uid, that.uid) - && Objects.equals(name, that.name); - } - - @Override - public int hashCode() { - return Objects.hash(id, ciod, uid, name); - } + private static final long serialVersionUID = 2885426916053925842L; + + private Long id; + + private String ciod; + + private String uid; + + private String name; + + public SOPClassUIDEntity() { + } + + public SOPClassUIDEntity(String ciod, String uid, String name) { + this.ciod = ciod; + this.uid = uid; + this.name = name; + } + + public SOPClassUIDEntity(String ciod) { + this.ciod = ciod; + } + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getCiod() { + return ciod; + } + + public void setCiod(String ciod) { + this.ciod = ciod; + } + + public String getUid() { + return uid; + } + + public void setUid(String uid) { + this.uid = uid; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + SOPClassUIDEntity that = (SOPClassUIDEntity) o; + return Objects.equals(id, that.id) && Objects.equals(ciod, that.ciod) && Objects.equals(uid, that.uid) + && Objects.equals(name, that.name); + } + + @Override + public int hashCode() { + return Objects.hash(id, ciod, uid, name); + } + } diff --git a/src/main/java/org/karnak/backend/data/entity/SecretEntity.java b/src/main/java/org/karnak/backend/data/entity/SecretEntity.java index d21127641..f425716b8 100644 --- a/src/main/java/org/karnak/backend/data/entity/SecretEntity.java +++ b/src/main/java/org/karnak/backend/data/entity/SecretEntity.java @@ -25,89 +25,92 @@ @Table(name = "secret") public class SecretEntity implements Serializable { - private Long id; - private ProjectEntity projectEntity; - private byte[] key; - private LocalDateTime creationDate; - private boolean active; - - public SecretEntity() {} - - public SecretEntity(byte[] key) { - this.key = key; - this.creationDate = LocalDateTime.now(); - } - - public SecretEntity(ProjectEntity projectEntity, byte[] key) { - this.projectEntity = projectEntity; - this.key = key; - this.creationDate = LocalDateTime.now(); - } - - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - @ManyToOne - @JoinColumn(name = "project_id") - public ProjectEntity getProjectEntity() { - return projectEntity; - } - - public void setProjectEntity(ProjectEntity projectEntity) { - this.projectEntity = projectEntity; - } - - public byte[] getKey() { - return key; - } - - public void setKey(byte[] key) { - this.key = key; - } - - public LocalDateTime getCreationDate() { - return creationDate; - } - - public void setCreationDate(LocalDateTime creationDate) { - this.creationDate = creationDate; - } - - public boolean isActive() { - return active; - } - - public void setActive(boolean active) { - this.active = active; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - SecretEntity that = (SecretEntity) o; - return active == that.active - && Objects.equals(id, that.id) - && Objects.equals(projectEntity, that.projectEntity) - && Arrays.equals(key, that.key) - && Objects.equals(creationDate, that.creationDate); - } - - @Override - public int hashCode() { - int result = Objects.hash(id, projectEntity, creationDate, active); - result = 31 * result + Arrays.hashCode(key); - return result; - } + private Long id; + + private ProjectEntity projectEntity; + + private byte[] key; + + private LocalDateTime creationDate; + + private boolean active; + + public SecretEntity() { + } + + public SecretEntity(byte[] key) { + this.key = key; + this.creationDate = LocalDateTime.now(); + } + + public SecretEntity(ProjectEntity projectEntity, byte[] key) { + this.projectEntity = projectEntity; + this.key = key; + this.creationDate = LocalDateTime.now(); + } + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + @ManyToOne + @JoinColumn(name = "project_id") + public ProjectEntity getProjectEntity() { + return projectEntity; + } + + public void setProjectEntity(ProjectEntity projectEntity) { + this.projectEntity = projectEntity; + } + + public byte[] getKey() { + return key; + } + + public void setKey(byte[] key) { + this.key = key; + } + + public LocalDateTime getCreationDate() { + return creationDate; + } + + public void setCreationDate(LocalDateTime creationDate) { + this.creationDate = creationDate; + } + + public boolean isActive() { + return active; + } + + public void setActive(boolean active) { + this.active = active; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + SecretEntity that = (SecretEntity) o; + return active == that.active && Objects.equals(id, that.id) && Objects.equals(projectEntity, that.projectEntity) + && Arrays.equals(key, that.key) && Objects.equals(creationDate, that.creationDate); + } + + @Override + public int hashCode() { + int result = Objects.hash(id, projectEntity, creationDate, active); + result = 31 * result + Arrays.hashCode(key); + return result; + } + } diff --git a/src/main/java/org/karnak/backend/data/entity/TagEntity.java b/src/main/java/org/karnak/backend/data/entity/TagEntity.java index 55263e937..48f8800ab 100644 --- a/src/main/java/org/karnak/backend/data/entity/TagEntity.java +++ b/src/main/java/org/karnak/backend/data/entity/TagEntity.java @@ -32,61 +32,65 @@ @DiscriminatorOptions(force = true) public abstract class TagEntity implements Serializable { - private static final long serialVersionUID = -1172918773653197764L; - - private Long id; - private ProfileElementEntity profileElementEntity; - private String tagValue; - - public TagEntity() {} - - public TagEntity(String tagValue, ProfileElementEntity profileElementEntity) { - this.tagValue = tagValue; - this.profileElementEntity = profileElementEntity; - } - - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - @ManyToOne() - @JoinColumn(name = "profile_element_id", nullable = false) - public ProfileElementEntity getProfileElementEntity() { - return profileElementEntity; - } - - public void setProfileElementEntity(ProfileElementEntity profileElementEntity) { - this.profileElementEntity = profileElementEntity; - } - - public String getTagValue() { - return tagValue; - } - - public void setTagValue(String tagValue) { - this.tagValue = tagValue; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - TagEntity tagEntity = (TagEntity) o; - return Objects.equals(id, tagEntity.id) && Objects.equals(tagValue, tagEntity.tagValue); - } - - @Override - public int hashCode() { - return Objects.hash(id, tagValue); - } + private static final long serialVersionUID = -1172918773653197764L; + + private Long id; + + private ProfileElementEntity profileElementEntity; + + private String tagValue; + + public TagEntity() { + } + + public TagEntity(String tagValue, ProfileElementEntity profileElementEntity) { + this.tagValue = tagValue; + this.profileElementEntity = profileElementEntity; + } + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + @ManyToOne() + @JoinColumn(name = "profile_element_id", nullable = false) + public ProfileElementEntity getProfileElementEntity() { + return profileElementEntity; + } + + public void setProfileElementEntity(ProfileElementEntity profileElementEntity) { + this.profileElementEntity = profileElementEntity; + } + + public String getTagValue() { + return tagValue; + } + + public void setTagValue(String tagValue) { + this.tagValue = tagValue; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + TagEntity tagEntity = (TagEntity) o; + return Objects.equals(id, tagEntity.id) && Objects.equals(tagValue, tagEntity.tagValue); + } + + @Override + public int hashCode() { + return Objects.hash(id, tagValue); + } + } diff --git a/src/main/java/org/karnak/backend/data/entity/TransferStatusEntity.java b/src/main/java/org/karnak/backend/data/entity/TransferStatusEntity.java index 52146aa8b..8b5b846db 100644 --- a/src/main/java/org/karnak/backend/data/entity/TransferStatusEntity.java +++ b/src/main/java/org/karnak/backend/data/entity/TransferStatusEntity.java @@ -34,502 +34,401 @@ @Table(name = "transfer_status") public class TransferStatusEntity implements Serializable { - private static final long serialVersionUID = -1542928573652195764L; - - private Long id; - @CsvRecurse private ForwardNodeEntity forwardNodeEntity; - private Long forwardNodeId; - @CsvRecurse private DestinationEntity destinationEntity; - private Long destinationId; - - @CsvDate(DateFormat.FORMAT_DDMMYYYY_SLASH_HHMMSS_2POINTS_SSSSSS_POINT) - private LocalDateTime transferDate; - - private boolean sent; - private String reason; - // Original - private String patientIdOriginal; - private String accessionNumberOriginal; - private String studyDescriptionOriginal; - - @CsvDate(DateFormat.FORMAT_DDMMYYYY_SLASH_HHMMSS_2POINTS_SSSSSS_POINT) - private LocalDateTime studyDateOriginal; - - private String studyUidOriginal; - private String serieDescriptionOriginal; - - @CsvDate(DateFormat.FORMAT_DDMMYYYY_SLASH_HHMMSS_2POINTS_SSSSSS_POINT) - private LocalDateTime serieDateOriginal; - - private String serieUidOriginal; - private String sopInstanceUidOriginal; - // To send - private String patientIdToSend; - private String accessionNumberToSend; - private String studyDescriptionToSend; - - @CsvDate(DateFormat.FORMAT_DDMMYYYY_SLASH_HHMMSS_2POINTS_SSSSSS_POINT) - private LocalDateTime studyDateToSend; - - private String studyUidToSend; - private String serieDescriptionToSend; - - @CsvDate(DateFormat.FORMAT_DDMMYYYY_SLASH_HHMMSS_2POINTS_SSSSSS_POINT) - private LocalDateTime serieDateToSend; - - private String serieUidToSend; - private String sopInstanceUidToSend; - - public TransferStatusEntity() {} - - public TransferStatusEntity( - Long forwardNodeId, - Long destinationId, - LocalDateTime transferDate, - boolean sent, - String reason, - String patientIdOriginal, - String accessionNumberOriginal, - String studyDescriptionOriginal, - LocalDateTime studyDateOriginal, - String studyUidOriginal, - String serieDescriptionOriginal, - LocalDateTime serieDateOriginal, - String serieUidOriginal, - String sopInstanceUidOriginal, - String patientIdToSend, - String accessionNumberToSend, - String studyDescriptionToSend, - LocalDateTime studyDateToSend, - String studyUidToSend, - String serieDescriptionToSend, - LocalDateTime serieDateToSend, - String serieUidToSend, - String sopInstanceUidToSend) { - this.forwardNodeId = forwardNodeId; - this.destinationId = destinationId; - this.transferDate = transferDate; - this.sent = sent; - this.reason = reason; - this.patientIdOriginal = patientIdOriginal; - this.accessionNumberOriginal = accessionNumberOriginal; - this.studyDescriptionOriginal = studyDescriptionOriginal; - this.studyDateOriginal = studyDateOriginal; - this.studyUidOriginal = studyUidOriginal; - this.serieDescriptionOriginal = serieDescriptionOriginal; - this.serieDateOriginal = serieDateOriginal; - this.serieUidOriginal = serieUidOriginal; - this.sopInstanceUidOriginal = sopInstanceUidOriginal; - this.patientIdToSend = patientIdToSend; - this.accessionNumberToSend = accessionNumberToSend; - this.studyDescriptionToSend = studyDescriptionToSend; - this.studyDateToSend = studyDateToSend; - this.studyUidToSend = studyUidToSend; - this.serieDescriptionToSend = serieDescriptionToSend; - this.serieDateToSend = serieDateToSend; - this.serieUidToSend = serieUidToSend; - this.sopInstanceUidToSend = sopInstanceUidToSend; - } - - public static TransferStatusEntity buildTransferStatusEntity( - Long forwardNodeId, - Long destinationId, - Attributes attributesOriginal, - Attributes attributesToSend, - boolean sent, - String reason) { - return new TransferStatusEntity( - forwardNodeId, - destinationId, - LocalDateTime.now(ZoneId.of("CET")), - sent, - reason, - attributesOriginal.getString(Tag.PatientID), - attributesOriginal.getString(Tag.AccessionNumber), - attributesOriginal.getString(Tag.StudyDescription), - DateTimeUtils.dateTime( - DateUtil.getDicomDate(attributesOriginal.getString(Tag.StudyDate)), - DateUtil.getDicomTime(attributesOriginal.getString(Tag.StudyTime))), - attributesOriginal.getString(Tag.StudyInstanceUID), - attributesOriginal.getString(Tag.SeriesDescription), - DateTimeUtils.dateTime( - DateUtil.getDicomDate(attributesOriginal.getString(Tag.SeriesDate)), - DateUtil.getDicomTime(attributesOriginal.getString(Tag.SeriesTime))), - attributesOriginal.getString(Tag.SeriesInstanceUID), - attributesOriginal.getString(Tag.SOPInstanceUID), - attributesToSend.getString(Tag.PatientID), - attributesToSend.getString(Tag.AccessionNumber), - attributesToSend.getString(Tag.StudyDescription), - DateTimeUtils.dateTime( - DateUtil.getDicomDate(attributesToSend.getString(Tag.StudyDate)), - DateUtil.getDicomTime(attributesToSend.getString(Tag.StudyTime))), - attributesToSend.getString(Tag.StudyInstanceUID), - attributesToSend.getString(Tag.SeriesDescription), - DateTimeUtils.dateTime( - DateUtil.getDicomDate(attributesToSend.getString(Tag.SeriesDate)), - DateUtil.getDicomTime(attributesToSend.getString(Tag.SeriesTime))), - attributesToSend.getString(Tag.SeriesInstanceUID), - attributesToSend.getString(Tag.SOPInstanceUID)); - } - - @Id - @SequenceGenerator( - name = "TRANSFER_STATUS_GEN", - sequenceName = "transfer_status_sequence", - allocationSize = 1) - @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "TRANSFER_STATUS_GEN") - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - @ManyToOne(targetEntity = ForwardNodeEntity.class) - @JoinColumn(name = "forward_node_id", nullable = false, insertable = false, updatable = false) - public ForwardNodeEntity getForwardNodeEntity() { - return forwardNodeEntity; - } - - public void setForwardNodeEntity(ForwardNodeEntity forwardNodeEntity) { - this.forwardNodeEntity = forwardNodeEntity; - } - - @Column(name = "forward_node_id") - public Long getForwardNodeId() { - return forwardNodeId; - } - - public void setForwardNodeId(Long forwardNodeId) { - this.forwardNodeId = forwardNodeId; - } - - @ManyToOne(targetEntity = DestinationEntity.class) - @JoinColumn(name = "destination_id", nullable = false, insertable = false, updatable = false) - public DestinationEntity getDestinationEntity() { - return destinationEntity; - } - - public void setDestinationEntity(DestinationEntity destinationEntity) { - this.destinationEntity = destinationEntity; - } - - @Column(name = "destination_id") - public Long getDestinationId() { - return destinationId; - } - - public void setDestinationId(Long destinationId) { - this.destinationId = destinationId; - } - - public LocalDateTime getTransferDate() { - return transferDate; - } - - public void setTransferDate(LocalDateTime transferDate) { - this.transferDate = transferDate; - } - - public boolean isSent() { - return sent; - } - - public void setSent(boolean sent) { - this.sent = sent; - } - - public String getReason() { - return reason; - } - - public void setReason(String reason) { - this.reason = reason; - } - - public String getPatientIdOriginal() { - return patientIdOriginal; - } - - public void setPatientIdOriginal(String patientIdOriginal) { - this.patientIdOriginal = patientIdOriginal; - } - - public String getAccessionNumberOriginal() { - return accessionNumberOriginal; - } - - public void setAccessionNumberOriginal(String accessionNumberOriginal) { - this.accessionNumberOriginal = accessionNumberOriginal; - } - - public String getStudyDescriptionOriginal() { - return studyDescriptionOriginal; - } - - public void setStudyDescriptionOriginal(String studyDescriptionOriginal) { - this.studyDescriptionOriginal = studyDescriptionOriginal; - } - - public LocalDateTime getStudyDateOriginal() { - return studyDateOriginal; - } - - public void setStudyDateOriginal(LocalDateTime studyDateOriginal) { - this.studyDateOriginal = studyDateOriginal; - } - - public String getStudyUidOriginal() { - return studyUidOriginal; - } - - public void setStudyUidOriginal(String studyUidOriginal) { - this.studyUidOriginal = studyUidOriginal; - } - - public String getSerieDescriptionOriginal() { - return serieDescriptionOriginal; - } + private static final long serialVersionUID = -1542928573652195764L; + + private Long id; + + @CsvRecurse + private ForwardNodeEntity forwardNodeEntity; + + private Long forwardNodeId; + + @CsvRecurse + private DestinationEntity destinationEntity; + + private Long destinationId; + + @CsvDate(DateFormat.FORMAT_DDMMYYYY_SLASH_HHMMSS_2POINTS_SSSSSS_POINT) + private LocalDateTime transferDate; + + private boolean sent; + + private String reason; + + // Original + private String patientIdOriginal; + + private String accessionNumberOriginal; + + private String studyDescriptionOriginal; + + @CsvDate(DateFormat.FORMAT_DDMMYYYY_SLASH_HHMMSS_2POINTS_SSSSSS_POINT) + private LocalDateTime studyDateOriginal; + + private String studyUidOriginal; + + private String serieDescriptionOriginal; + + @CsvDate(DateFormat.FORMAT_DDMMYYYY_SLASH_HHMMSS_2POINTS_SSSSSS_POINT) + private LocalDateTime serieDateOriginal; + + private String serieUidOriginal; + + private String sopInstanceUidOriginal; + + // To send + private String patientIdToSend; + + private String accessionNumberToSend; + + private String studyDescriptionToSend; + + @CsvDate(DateFormat.FORMAT_DDMMYYYY_SLASH_HHMMSS_2POINTS_SSSSSS_POINT) + private LocalDateTime studyDateToSend; + + private String studyUidToSend; + + private String serieDescriptionToSend; + + @CsvDate(DateFormat.FORMAT_DDMMYYYY_SLASH_HHMMSS_2POINTS_SSSSSS_POINT) + private LocalDateTime serieDateToSend; + + private String serieUidToSend; + + private String sopInstanceUidToSend; + + public TransferStatusEntity() { + } + + public TransferStatusEntity(Long forwardNodeId, Long destinationId, LocalDateTime transferDate, boolean sent, + String reason, String patientIdOriginal, String accessionNumberOriginal, String studyDescriptionOriginal, + LocalDateTime studyDateOriginal, String studyUidOriginal, String serieDescriptionOriginal, + LocalDateTime serieDateOriginal, String serieUidOriginal, String sopInstanceUidOriginal, + String patientIdToSend, String accessionNumberToSend, String studyDescriptionToSend, + LocalDateTime studyDateToSend, String studyUidToSend, String serieDescriptionToSend, + LocalDateTime serieDateToSend, String serieUidToSend, String sopInstanceUidToSend) { + this.forwardNodeId = forwardNodeId; + this.destinationId = destinationId; + this.transferDate = transferDate; + this.sent = sent; + this.reason = reason; + this.patientIdOriginal = patientIdOriginal; + this.accessionNumberOriginal = accessionNumberOriginal; + this.studyDescriptionOriginal = studyDescriptionOriginal; + this.studyDateOriginal = studyDateOriginal; + this.studyUidOriginal = studyUidOriginal; + this.serieDescriptionOriginal = serieDescriptionOriginal; + this.serieDateOriginal = serieDateOriginal; + this.serieUidOriginal = serieUidOriginal; + this.sopInstanceUidOriginal = sopInstanceUidOriginal; + this.patientIdToSend = patientIdToSend; + this.accessionNumberToSend = accessionNumberToSend; + this.studyDescriptionToSend = studyDescriptionToSend; + this.studyDateToSend = studyDateToSend; + this.studyUidToSend = studyUidToSend; + this.serieDescriptionToSend = serieDescriptionToSend; + this.serieDateToSend = serieDateToSend; + this.serieUidToSend = serieUidToSend; + this.sopInstanceUidToSend = sopInstanceUidToSend; + } + + public static TransferStatusEntity buildTransferStatusEntity(Long forwardNodeId, Long destinationId, + Attributes attributesOriginal, Attributes attributesToSend, boolean sent, String reason) { + return new TransferStatusEntity(forwardNodeId, destinationId, LocalDateTime.now(ZoneId.of("CET")), sent, reason, + attributesOriginal.getString(Tag.PatientID), attributesOriginal.getString(Tag.AccessionNumber), + attributesOriginal.getString(Tag.StudyDescription), + DateTimeUtils.dateTime(DateUtil.getDicomDate(attributesOriginal.getString(Tag.StudyDate)), + DateUtil.getDicomTime(attributesOriginal.getString(Tag.StudyTime))), + attributesOriginal.getString(Tag.StudyInstanceUID), attributesOriginal.getString(Tag.SeriesDescription), + DateTimeUtils.dateTime(DateUtil.getDicomDate(attributesOriginal.getString(Tag.SeriesDate)), + DateUtil.getDicomTime(attributesOriginal.getString(Tag.SeriesTime))), + attributesOriginal.getString(Tag.SeriesInstanceUID), attributesOriginal.getString(Tag.SOPInstanceUID), + attributesToSend.getString(Tag.PatientID), attributesToSend.getString(Tag.AccessionNumber), + attributesToSend.getString(Tag.StudyDescription), + DateTimeUtils.dateTime(DateUtil.getDicomDate(attributesToSend.getString(Tag.StudyDate)), + DateUtil.getDicomTime(attributesToSend.getString(Tag.StudyTime))), + attributesToSend.getString(Tag.StudyInstanceUID), attributesToSend.getString(Tag.SeriesDescription), + DateTimeUtils.dateTime(DateUtil.getDicomDate(attributesToSend.getString(Tag.SeriesDate)), + DateUtil.getDicomTime(attributesToSend.getString(Tag.SeriesTime))), + attributesToSend.getString(Tag.SeriesInstanceUID), attributesToSend.getString(Tag.SOPInstanceUID)); + } + + @Id + @SequenceGenerator(name = "TRANSFER_STATUS_GEN", sequenceName = "transfer_status_sequence", allocationSize = 1) + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "TRANSFER_STATUS_GEN") + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + @ManyToOne(targetEntity = ForwardNodeEntity.class) + @JoinColumn(name = "forward_node_id", nullable = false, insertable = false, updatable = false) + public ForwardNodeEntity getForwardNodeEntity() { + return forwardNodeEntity; + } + + public void setForwardNodeEntity(ForwardNodeEntity forwardNodeEntity) { + this.forwardNodeEntity = forwardNodeEntity; + } + + @Column(name = "forward_node_id") + public Long getForwardNodeId() { + return forwardNodeId; + } + + public void setForwardNodeId(Long forwardNodeId) { + this.forwardNodeId = forwardNodeId; + } + + @ManyToOne(targetEntity = DestinationEntity.class) + @JoinColumn(name = "destination_id", nullable = false, insertable = false, updatable = false) + public DestinationEntity getDestinationEntity() { + return destinationEntity; + } + + public void setDestinationEntity(DestinationEntity destinationEntity) { + this.destinationEntity = destinationEntity; + } + + @Column(name = "destination_id") + public Long getDestinationId() { + return destinationId; + } + + public void setDestinationId(Long destinationId) { + this.destinationId = destinationId; + } + + public LocalDateTime getTransferDate() { + return transferDate; + } + + public void setTransferDate(LocalDateTime transferDate) { + this.transferDate = transferDate; + } + + public boolean isSent() { + return sent; + } + + public void setSent(boolean sent) { + this.sent = sent; + } + + public String getReason() { + return reason; + } + + public void setReason(String reason) { + this.reason = reason; + } + + public String getPatientIdOriginal() { + return patientIdOriginal; + } + + public void setPatientIdOriginal(String patientIdOriginal) { + this.patientIdOriginal = patientIdOriginal; + } + + public String getAccessionNumberOriginal() { + return accessionNumberOriginal; + } + + public void setAccessionNumberOriginal(String accessionNumberOriginal) { + this.accessionNumberOriginal = accessionNumberOriginal; + } + + public String getStudyDescriptionOriginal() { + return studyDescriptionOriginal; + } + + public void setStudyDescriptionOriginal(String studyDescriptionOriginal) { + this.studyDescriptionOriginal = studyDescriptionOriginal; + } + + public LocalDateTime getStudyDateOriginal() { + return studyDateOriginal; + } + + public void setStudyDateOriginal(LocalDateTime studyDateOriginal) { + this.studyDateOriginal = studyDateOriginal; + } + + public String getStudyUidOriginal() { + return studyUidOriginal; + } + + public void setStudyUidOriginal(String studyUidOriginal) { + this.studyUidOriginal = studyUidOriginal; + } + + public String getSerieDescriptionOriginal() { + return serieDescriptionOriginal; + } + + public void setSerieDescriptionOriginal(String serieDescriptionOriginal) { + this.serieDescriptionOriginal = serieDescriptionOriginal; + } + + public LocalDateTime getSerieDateOriginal() { + return serieDateOriginal; + } + + public void setSerieDateOriginal(LocalDateTime serieDateOriginal) { + this.serieDateOriginal = serieDateOriginal; + } + + public String getSerieUidOriginal() { + return serieUidOriginal; + } + + public void setSerieUidOriginal(String serieUidOriginal) { + this.serieUidOriginal = serieUidOriginal; + } + + public String getSopInstanceUidOriginal() { + return sopInstanceUidOriginal; + } + + public void setSopInstanceUidOriginal(String sopInstanceUidOriginal) { + this.sopInstanceUidOriginal = sopInstanceUidOriginal; + } + + public String getPatientIdToSend() { + return patientIdToSend; + } + + public void setPatientIdToSend(String patientIdToSend) { + this.patientIdToSend = patientIdToSend; + } + + public String getAccessionNumberToSend() { + return accessionNumberToSend; + } + + public void setAccessionNumberToSend(String accessionNumberToSend) { + this.accessionNumberToSend = accessionNumberToSend; + } + + public String getStudyDescriptionToSend() { + return studyDescriptionToSend; + } + + public void setStudyDescriptionToSend(String studyDescriptionToSend) { + this.studyDescriptionToSend = studyDescriptionToSend; + } + + public LocalDateTime getStudyDateToSend() { + return studyDateToSend; + } + + public void setStudyDateToSend(LocalDateTime studyDateToSend) { + this.studyDateToSend = studyDateToSend; + } + + public String getStudyUidToSend() { + return studyUidToSend; + } + + public void setStudyUidToSend(String studyUidToSend) { + this.studyUidToSend = studyUidToSend; + } + + public String getSerieDescriptionToSend() { + return serieDescriptionToSend; + } + + public void setSerieDescriptionToSend(String serieDescriptionToSend) { + this.serieDescriptionToSend = serieDescriptionToSend; + } + + public LocalDateTime getSerieDateToSend() { + return serieDateToSend; + } + + public void setSerieDateToSend(LocalDateTime serieDateToSend) { + this.serieDateToSend = serieDateToSend; + } + + public String getSerieUidToSend() { + return serieUidToSend; + } + + public void setSerieUidToSend(String serieUidToSend) { + this.serieUidToSend = serieUidToSend; + } + + public String getSopInstanceUidToSend() { + return sopInstanceUidToSend; + } + + public void setSopInstanceUidToSend(String sopInstanceUidToSend) { + this.sopInstanceUidToSend = sopInstanceUidToSend; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + TransferStatusEntity that = (TransferStatusEntity) o; + return sent == that.sent && Objects.equals(id, that.id) + && Objects.equals(forwardNodeEntity, that.forwardNodeEntity) + && Objects.equals(forwardNodeId, that.forwardNodeId) + && Objects.equals(destinationEntity, that.destinationEntity) + && Objects.equals(destinationId, that.destinationId) && Objects.equals(transferDate, that.transferDate) + && Objects.equals(reason, that.reason) && Objects.equals(patientIdOriginal, that.patientIdOriginal) + && Objects.equals(accessionNumberOriginal, that.accessionNumberOriginal) + && Objects.equals(studyDescriptionOriginal, that.studyDescriptionOriginal) + && Objects.equals(studyDateOriginal, that.studyDateOriginal) + && Objects.equals(studyUidOriginal, that.studyUidOriginal) + && Objects.equals(serieDescriptionOriginal, that.serieDescriptionOriginal) + && Objects.equals(serieDateOriginal, that.serieDateOriginal) + && Objects.equals(serieUidOriginal, that.serieUidOriginal) + && Objects.equals(sopInstanceUidOriginal, that.sopInstanceUidOriginal) + && Objects.equals(patientIdToSend, that.patientIdToSend) + && Objects.equals(accessionNumberToSend, that.accessionNumberToSend) + && Objects.equals(studyDescriptionToSend, that.studyDescriptionToSend) + && Objects.equals(studyDateToSend, that.studyDateToSend) + && Objects.equals(studyUidToSend, that.studyUidToSend) + && Objects.equals(serieDescriptionToSend, that.serieDescriptionToSend) + && Objects.equals(serieDateToSend, that.serieDateToSend) + && Objects.equals(serieUidToSend, that.serieUidToSend) + && Objects.equals(sopInstanceUidToSend, that.sopInstanceUidToSend); + } + + @Override + public int hashCode() { + return Objects.hash(id, forwardNodeEntity, forwardNodeId, destinationEntity, destinationId, transferDate, sent, + reason, patientIdOriginal, accessionNumberOriginal, studyDescriptionOriginal, studyDateOriginal, + studyUidOriginal, serieDescriptionOriginal, serieDateOriginal, serieUidOriginal, sopInstanceUidOriginal, + patientIdToSend, accessionNumberToSend, studyDescriptionToSend, studyDateToSend, studyUidToSend, + serieDescriptionToSend, serieDateToSend, serieUidToSend, sopInstanceUidToSend); + } + + @Override + public String toString() { + return "TransferStatusEntity{" + "id=" + id + ", forwardNodeEntity=" + forwardNodeEntity + ", forwardNodeId=" + + forwardNodeId + ", destinationEntity=" + destinationEntity + ", destinationId=" + destinationId + + ", transferDate=" + transferDate + ", sent=" + sent + ", reason='" + reason + '\'' + + ", patientIdOriginal='" + patientIdOriginal + '\'' + ", accessionNumberOriginal='" + + accessionNumberOriginal + '\'' + ", studyDescriptionOriginal='" + studyDescriptionOriginal + '\'' + + ", studyDateOriginal=" + studyDateOriginal + ", studyUidOriginal='" + studyUidOriginal + '\'' + + ", serieDescriptionOriginal='" + serieDescriptionOriginal + '\'' + ", serieDateOriginal=" + + serieDateOriginal + ", serieUidOriginal='" + serieUidOriginal + '\'' + ", sopInstanceUidOriginal='" + + sopInstanceUidOriginal + '\'' + ", patientIdToSend='" + patientIdToSend + '\'' + + ", accessionNumberToSend='" + accessionNumberToSend + '\'' + ", studyDescriptionToSend='" + + studyDescriptionToSend + '\'' + ", studyDateToSend=" + studyDateToSend + ", studyUidToSend='" + + studyUidToSend + '\'' + ", serieDescriptionToSend='" + serieDescriptionToSend + '\'' + + ", serieDateToSend=" + serieDateToSend + ", serieUidToSend='" + serieUidToSend + '\'' + + ", sopInstanceUidToSend='" + sopInstanceUidToSend + '\'' + '}'; + } - public void setSerieDescriptionOriginal(String serieDescriptionOriginal) { - this.serieDescriptionOriginal = serieDescriptionOriginal; - } - - public LocalDateTime getSerieDateOriginal() { - return serieDateOriginal; - } - - public void setSerieDateOriginal(LocalDateTime serieDateOriginal) { - this.serieDateOriginal = serieDateOriginal; - } - - public String getSerieUidOriginal() { - return serieUidOriginal; - } - - public void setSerieUidOriginal(String serieUidOriginal) { - this.serieUidOriginal = serieUidOriginal; - } - - public String getSopInstanceUidOriginal() { - return sopInstanceUidOriginal; - } - - public void setSopInstanceUidOriginal(String sopInstanceUidOriginal) { - this.sopInstanceUidOriginal = sopInstanceUidOriginal; - } - - public String getPatientIdToSend() { - return patientIdToSend; - } - - public void setPatientIdToSend(String patientIdToSend) { - this.patientIdToSend = patientIdToSend; - } - - public String getAccessionNumberToSend() { - return accessionNumberToSend; - } - - public void setAccessionNumberToSend(String accessionNumberToSend) { - this.accessionNumberToSend = accessionNumberToSend; - } - - public String getStudyDescriptionToSend() { - return studyDescriptionToSend; - } - - public void setStudyDescriptionToSend(String studyDescriptionToSend) { - this.studyDescriptionToSend = studyDescriptionToSend; - } - - public LocalDateTime getStudyDateToSend() { - return studyDateToSend; - } - - public void setStudyDateToSend(LocalDateTime studyDateToSend) { - this.studyDateToSend = studyDateToSend; - } - - public String getStudyUidToSend() { - return studyUidToSend; - } - - public void setStudyUidToSend(String studyUidToSend) { - this.studyUidToSend = studyUidToSend; - } - - public String getSerieDescriptionToSend() { - return serieDescriptionToSend; - } - - public void setSerieDescriptionToSend(String serieDescriptionToSend) { - this.serieDescriptionToSend = serieDescriptionToSend; - } - - public LocalDateTime getSerieDateToSend() { - return serieDateToSend; - } - - public void setSerieDateToSend(LocalDateTime serieDateToSend) { - this.serieDateToSend = serieDateToSend; - } - - public String getSerieUidToSend() { - return serieUidToSend; - } - - public void setSerieUidToSend(String serieUidToSend) { - this.serieUidToSend = serieUidToSend; - } - - public String getSopInstanceUidToSend() { - return sopInstanceUidToSend; - } - - public void setSopInstanceUidToSend(String sopInstanceUidToSend) { - this.sopInstanceUidToSend = sopInstanceUidToSend; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - TransferStatusEntity that = (TransferStatusEntity) o; - return sent == that.sent - && Objects.equals(id, that.id) - && Objects.equals(forwardNodeEntity, that.forwardNodeEntity) - && Objects.equals(forwardNodeId, that.forwardNodeId) - && Objects.equals(destinationEntity, that.destinationEntity) - && Objects.equals(destinationId, that.destinationId) - && Objects.equals(transferDate, that.transferDate) - && Objects.equals(reason, that.reason) - && Objects.equals(patientIdOriginal, that.patientIdOriginal) - && Objects.equals(accessionNumberOriginal, that.accessionNumberOriginal) - && Objects.equals(studyDescriptionOriginal, that.studyDescriptionOriginal) - && Objects.equals(studyDateOriginal, that.studyDateOriginal) - && Objects.equals(studyUidOriginal, that.studyUidOriginal) - && Objects.equals(serieDescriptionOriginal, that.serieDescriptionOriginal) - && Objects.equals(serieDateOriginal, that.serieDateOriginal) - && Objects.equals(serieUidOriginal, that.serieUidOriginal) - && Objects.equals(sopInstanceUidOriginal, that.sopInstanceUidOriginal) - && Objects.equals(patientIdToSend, that.patientIdToSend) - && Objects.equals(accessionNumberToSend, that.accessionNumberToSend) - && Objects.equals(studyDescriptionToSend, that.studyDescriptionToSend) - && Objects.equals(studyDateToSend, that.studyDateToSend) - && Objects.equals(studyUidToSend, that.studyUidToSend) - && Objects.equals(serieDescriptionToSend, that.serieDescriptionToSend) - && Objects.equals(serieDateToSend, that.serieDateToSend) - && Objects.equals(serieUidToSend, that.serieUidToSend) - && Objects.equals(sopInstanceUidToSend, that.sopInstanceUidToSend); - } - - @Override - public int hashCode() { - return Objects.hash( - id, - forwardNodeEntity, - forwardNodeId, - destinationEntity, - destinationId, - transferDate, - sent, - reason, - patientIdOriginal, - accessionNumberOriginal, - studyDescriptionOriginal, - studyDateOriginal, - studyUidOriginal, - serieDescriptionOriginal, - serieDateOriginal, - serieUidOriginal, - sopInstanceUidOriginal, - patientIdToSend, - accessionNumberToSend, - studyDescriptionToSend, - studyDateToSend, - studyUidToSend, - serieDescriptionToSend, - serieDateToSend, - serieUidToSend, - sopInstanceUidToSend); - } - - @Override - public String toString() { - return "TransferStatusEntity{" - + "id=" - + id - + ", forwardNodeEntity=" - + forwardNodeEntity - + ", forwardNodeId=" - + forwardNodeId - + ", destinationEntity=" - + destinationEntity - + ", destinationId=" - + destinationId - + ", transferDate=" - + transferDate - + ", sent=" - + sent - + ", reason='" - + reason - + '\'' - + ", patientIdOriginal='" - + patientIdOriginal - + '\'' - + ", accessionNumberOriginal='" - + accessionNumberOriginal - + '\'' - + ", studyDescriptionOriginal='" - + studyDescriptionOriginal - + '\'' - + ", studyDateOriginal=" - + studyDateOriginal - + ", studyUidOriginal='" - + studyUidOriginal - + '\'' - + ", serieDescriptionOriginal='" - + serieDescriptionOriginal - + '\'' - + ", serieDateOriginal=" - + serieDateOriginal - + ", serieUidOriginal='" - + serieUidOriginal - + '\'' - + ", sopInstanceUidOriginal='" - + sopInstanceUidOriginal - + '\'' - + ", patientIdToSend='" - + patientIdToSend - + '\'' - + ", accessionNumberToSend='" - + accessionNumberToSend - + '\'' - + ", studyDescriptionToSend='" - + studyDescriptionToSend - + '\'' - + ", studyDateToSend=" - + studyDateToSend - + ", studyUidToSend='" - + studyUidToSend - + '\'' - + ", serieDescriptionToSend='" - + serieDescriptionToSend - + '\'' - + ", serieDateToSend=" - + serieDateToSend - + ", serieUidToSend='" - + serieUidToSend - + '\'' - + ", sopInstanceUidToSend='" - + sopInstanceUidToSend - + '\'' - + '}'; - } } diff --git a/src/main/java/org/karnak/backend/data/entity/VersionEntity.java b/src/main/java/org/karnak/backend/data/entity/VersionEntity.java index 4586c0efa..98aee0068 100644 --- a/src/main/java/org/karnak/backend/data/entity/VersionEntity.java +++ b/src/main/java/org/karnak/backend/data/entity/VersionEntity.java @@ -21,41 +21,43 @@ @Table(name = "version") public class VersionEntity implements Serializable { - private Long id; - private long gatewaySetup; - - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public long getGatewaySetup() { - return gatewaySetup; - } - - public void setGatewaySetup(long gatewaySetup) { - this.gatewaySetup = gatewaySetup; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - VersionEntity that = (VersionEntity) o; - return gatewaySetup == that.gatewaySetup && Objects.equals(id, that.id); - } - - @Override - public int hashCode() { - return Objects.hash(id, gatewaySetup); - } + private Long id; + + private long gatewaySetup; + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public long getGatewaySetup() { + return gatewaySetup; + } + + public void setGatewaySetup(long gatewaySetup) { + this.gatewaySetup = gatewaySetup; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + VersionEntity that = (VersionEntity) o; + return gatewaySetup == that.gatewaySetup && Objects.equals(id, that.id); + } + + @Override + public int hashCode() { + return Objects.hash(id, gatewaySetup); + } + } diff --git a/src/main/java/org/karnak/backend/data/repo/ArgumentRepo.java b/src/main/java/org/karnak/backend/data/repo/ArgumentRepo.java index acdf1ea14..d267f951f 100644 --- a/src/main/java/org/karnak/backend/data/repo/ArgumentRepo.java +++ b/src/main/java/org/karnak/backend/data/repo/ArgumentRepo.java @@ -14,4 +14,6 @@ import org.springframework.stereotype.Repository; @Repository -public interface ArgumentRepo extends JpaRepository {} +public interface ArgumentRepo extends JpaRepository { + +} diff --git a/src/main/java/org/karnak/backend/data/repo/DestinationRepo.java b/src/main/java/org/karnak/backend/data/repo/DestinationRepo.java index b981f6dfc..deaf25dc0 100644 --- a/src/main/java/org/karnak/backend/data/repo/DestinationRepo.java +++ b/src/main/java/org/karnak/backend/data/repo/DestinationRepo.java @@ -14,4 +14,6 @@ import org.springframework.stereotype.Repository; @Repository -public interface DestinationRepo extends JpaRepository {} +public interface DestinationRepo extends JpaRepository { + +} diff --git a/src/main/java/org/karnak/backend/data/repo/DicomSourceNodeRepo.java b/src/main/java/org/karnak/backend/data/repo/DicomSourceNodeRepo.java index 432f5671e..556ae8a14 100644 --- a/src/main/java/org/karnak/backend/data/repo/DicomSourceNodeRepo.java +++ b/src/main/java/org/karnak/backend/data/repo/DicomSourceNodeRepo.java @@ -14,4 +14,6 @@ import org.springframework.stereotype.Repository; @Repository -public interface DicomSourceNodeRepo extends JpaRepository {} +public interface DicomSourceNodeRepo extends JpaRepository { + +} diff --git a/src/main/java/org/karnak/backend/data/repo/ForwardNodeRepo.java b/src/main/java/org/karnak/backend/data/repo/ForwardNodeRepo.java index 239fbea20..f16a9617e 100644 --- a/src/main/java/org/karnak/backend/data/repo/ForwardNodeRepo.java +++ b/src/main/java/org/karnak/backend/data/repo/ForwardNodeRepo.java @@ -14,4 +14,6 @@ import org.springframework.stereotype.Repository; @Repository -public interface ForwardNodeRepo extends JpaRepository {} +public interface ForwardNodeRepo extends JpaRepository { + +} diff --git a/src/main/java/org/karnak/backend/data/repo/KheopsAlbumsRepo.java b/src/main/java/org/karnak/backend/data/repo/KheopsAlbumsRepo.java index b875e9609..372c95abd 100644 --- a/src/main/java/org/karnak/backend/data/repo/KheopsAlbumsRepo.java +++ b/src/main/java/org/karnak/backend/data/repo/KheopsAlbumsRepo.java @@ -18,5 +18,6 @@ @Repository public interface KheopsAlbumsRepo extends JpaRepository { - List findAllByDestinationEntity(DestinationEntity destinationEntity); + List findAllByDestinationEntity(DestinationEntity destinationEntity); + } diff --git a/src/main/java/org/karnak/backend/data/repo/MaskRepo.java b/src/main/java/org/karnak/backend/data/repo/MaskRepo.java index 46bde1017..66ca3943d 100644 --- a/src/main/java/org/karnak/backend/data/repo/MaskRepo.java +++ b/src/main/java/org/karnak/backend/data/repo/MaskRepo.java @@ -14,4 +14,6 @@ import org.springframework.stereotype.Repository; @Repository -public interface MaskRepo extends JpaRepository {} +public interface MaskRepo extends JpaRepository { + +} diff --git a/src/main/java/org/karnak/backend/data/repo/ProfileElementRepo.java b/src/main/java/org/karnak/backend/data/repo/ProfileElementRepo.java index 62837db5d..4b441c808 100644 --- a/src/main/java/org/karnak/backend/data/repo/ProfileElementRepo.java +++ b/src/main/java/org/karnak/backend/data/repo/ProfileElementRepo.java @@ -14,4 +14,6 @@ import org.springframework.stereotype.Repository; @Repository -public interface ProfileElementRepo extends JpaRepository {} +public interface ProfileElementRepo extends JpaRepository { + +} diff --git a/src/main/java/org/karnak/backend/data/repo/ProfileRepo.java b/src/main/java/org/karnak/backend/data/repo/ProfileRepo.java index f386b74f9..c764c1bd9 100644 --- a/src/main/java/org/karnak/backend/data/repo/ProfileRepo.java +++ b/src/main/java/org/karnak/backend/data/repo/ProfileRepo.java @@ -16,7 +16,8 @@ @Repository public interface ProfileRepo extends JpaRepository { - Boolean existsByName(String name); + Boolean existsByName(String name); + + Boolean existsByNameAndByDefault(String name, Boolean byDefault); - Boolean existsByNameAndByDefault(String name, Boolean byDefault); } diff --git a/src/main/java/org/karnak/backend/data/repo/ProjectRepo.java b/src/main/java/org/karnak/backend/data/repo/ProjectRepo.java index 192ba9e45..c80ac66dd 100644 --- a/src/main/java/org/karnak/backend/data/repo/ProjectRepo.java +++ b/src/main/java/org/karnak/backend/data/repo/ProjectRepo.java @@ -14,4 +14,6 @@ import org.springframework.stereotype.Repository; @Repository -public interface ProjectRepo extends JpaRepository {} +public interface ProjectRepo extends JpaRepository { + +} diff --git a/src/main/java/org/karnak/backend/data/repo/SOPClassUIDRepo.java b/src/main/java/org/karnak/backend/data/repo/SOPClassUIDRepo.java index 6d418645a..dfb02b9d5 100644 --- a/src/main/java/org/karnak/backend/data/repo/SOPClassUIDRepo.java +++ b/src/main/java/org/karnak/backend/data/repo/SOPClassUIDRepo.java @@ -16,9 +16,10 @@ @Repository public interface SOPClassUIDRepo extends JpaRepository { - SOPClassUIDEntity getSOPClassUIDByName(String name); + SOPClassUIDEntity getSOPClassUIDByName(String name); - SOPClassUIDEntity getSOPClassUIDById(Long id); + SOPClassUIDEntity getSOPClassUIDById(Long id); + + Boolean existsByCiodAndUidAndName(String ciod, String uid, String name); - Boolean existsByCiodAndUidAndName(String ciod, String uid, String name); } diff --git a/src/main/java/org/karnak/backend/data/repo/SecretRepo.java b/src/main/java/org/karnak/backend/data/repo/SecretRepo.java index c4ebefbcc..8fe5c4289 100644 --- a/src/main/java/org/karnak/backend/data/repo/SecretRepo.java +++ b/src/main/java/org/karnak/backend/data/repo/SecretRepo.java @@ -14,4 +14,6 @@ import org.springframework.stereotype.Repository; @Repository -public interface SecretRepo extends JpaRepository {} +public interface SecretRepo extends JpaRepository { + +} diff --git a/src/main/java/org/karnak/backend/data/repo/TagRepo.java b/src/main/java/org/karnak/backend/data/repo/TagRepo.java index cf964b068..24962e88f 100644 --- a/src/main/java/org/karnak/backend/data/repo/TagRepo.java +++ b/src/main/java/org/karnak/backend/data/repo/TagRepo.java @@ -14,4 +14,6 @@ import org.springframework.stereotype.Repository; @Repository -public interface TagRepo extends JpaRepository {} +public interface TagRepo extends JpaRepository { + +} diff --git a/src/main/java/org/karnak/backend/data/repo/TransferStatusRepo.java b/src/main/java/org/karnak/backend/data/repo/TransferStatusRepo.java index 0c777ef8e..1a94bb68a 100644 --- a/src/main/java/org/karnak/backend/data/repo/TransferStatusRepo.java +++ b/src/main/java/org/karnak/backend/data/repo/TransferStatusRepo.java @@ -20,33 +20,29 @@ @Repository public interface TransferStatusRepo - extends JpaRepository, - JpaSpecificationExecutor { + extends JpaRepository, JpaSpecificationExecutor { - /** - * Look for TransferStatusEntity for a destination - * - * @param destinationId Destination id - * @return TransferStatusEntity found - */ - List findByDestinationId(Long destinationId); + /** + * Look for TransferStatusEntity for a destination + * @param destinationId Destination id + * @return TransferStatusEntity found + */ + List findByDestinationId(Long destinationId); - /** - * Look for TransferStatusEntity for a destination and after the last check date - * - * @param destinationId Destination id - * @param lastCheck Date of the last check - * @return TransferStatusEntity found - */ - List findByDestinationIdAndTransferDateAfter( - Long destinationId, LocalDateTime lastCheck); + /** + * Look for TransferStatusEntity for a destination and after the last check date + * @param destinationId Destination id + * @param lastCheck Date of the last check + * @return TransferStatusEntity found + */ + List findByDestinationIdAndTransferDateAfter(Long destinationId, LocalDateTime lastCheck); + + /** + * Look for oldest transfer status entities, number of entities found is limited by + * the pageRequest + * @param pageable Limit the number of records found + * @return TransferEntities found + */ + Page findAllByOrderByTransferDateAsc(Pageable pageable); - /** - * Look for oldest transfer status entities, number of entities found is limited by the - * pageRequest - * - * @param pageable Limit the number of records found - * @return TransferEntities found - */ - Page findAllByOrderByTransferDateAsc(Pageable pageable); } diff --git a/src/main/java/org/karnak/backend/data/repo/VersionRepo.java b/src/main/java/org/karnak/backend/data/repo/VersionRepo.java index eacc2e4e7..80a2f0031 100644 --- a/src/main/java/org/karnak/backend/data/repo/VersionRepo.java +++ b/src/main/java/org/karnak/backend/data/repo/VersionRepo.java @@ -16,10 +16,10 @@ @Repository public interface VersionRepo extends JpaRepository { - /** - * Find last record of the table version - * - * @return VersionEntity found - */ - VersionEntity findTopByOrderByIdDesc(); + /** + * Find last record of the table version + * @return VersionEntity found + */ + VersionEntity findTopByOrderByIdDesc(); + } diff --git a/src/main/java/org/karnak/backend/data/repo/specification/TransferStatusSpecification.java b/src/main/java/org/karnak/backend/data/repo/specification/TransferStatusSpecification.java index 9df94a702..4751d6637 100644 --- a/src/main/java/org/karnak/backend/data/repo/specification/TransferStatusSpecification.java +++ b/src/main/java/org/karnak/backend/data/repo/specification/TransferStatusSpecification.java @@ -28,173 +28,144 @@ /** Transfer status specification: used to look for entries depending on criteria */ public class TransferStatusSpecification implements Specification { - @Serial private static final long serialVersionUID = -939448741462690254L; - - // Like character - private static final String LIKE = "%"; - - // Criteria to look for - private final TransferStatusFilter transferStatusFilter; - - /** - * Constructor with filter - * - * @param transferStatusFilter Criteria to look for - */ - public TransferStatusSpecification(TransferStatusFilter transferStatusFilter) { - this.transferStatusFilter = transferStatusFilter; - } - - @Override - public Predicate toPredicate( - Root root, CriteriaQuery query, CriteriaBuilder criteriaBuilder) { - // Predicates to fill - List predicates = new ArrayList<>(); - - // Paths - // Study Uid - Path pStudyUidOriginal = root.get("studyUidOriginal"); - Path pStudyUidToSend = root.get("studyUidToSend"); - // Serie Uid - Path pSerieUidOriginal = root.get("serieUidOriginal"); - Path pSerieUidToSend = root.get("serieUidToSend"); - // Sop Instance Uid - Path pSopInstanceUidOriginal = root.get("sopInstanceUidOriginal"); - Path pSopInstanceUidToSend = root.get("sopInstanceUidToSend"); - // Status - Path pSent = root.get("sent"); - // Transfer date - Path pTransferDate = root.get("transferDate"); - - // Build criteria - if (transferStatusFilter != null) { - // Study Uid - buildCriteriaStudyUid(criteriaBuilder, predicates, pStudyUidOriginal, pStudyUidToSend); - // Serie Uid - buildCriteriaSerieUid(criteriaBuilder, predicates, pSerieUidOriginal, pSerieUidToSend); - // Sop Instance Uid - buildCriteriaSopInstanceUid( - criteriaBuilder, predicates, pSopInstanceUidOriginal, pSopInstanceUidToSend); - // Sent - buildCriteriaSent(criteriaBuilder, predicates, pSent); - // Transfer Date - buildCriteriaTransferDate(criteriaBuilder, predicates, pTransferDate); - } - - return criteriaBuilder.and(predicates.toArray(new Predicate[] {})); - } - - /** - * Build criteria for study uid - * - * @param criteriaBuilder CriteriaBuilder - * @param predicates Predicates to build - * @param pStudyUidOriginal Path of study uid original - * @param pStudyUidToSend Path of study uid to send - */ - private void buildCriteriaStudyUid( - CriteriaBuilder criteriaBuilder, - List predicates, - Path pStudyUidOriginal, - Path pStudyUidToSend) { - if (transferStatusFilter.getStudyUid() != null - && StringUtils.isNotBlank(transferStatusFilter.getStudyUid())) { - predicates.add( - criteriaBuilder.or( - criteriaBuilder.like( - pStudyUidOriginal, LIKE + transferStatusFilter.getStudyUid().trim() + LIKE), - criteriaBuilder.like( - pStudyUidToSend, LIKE + transferStatusFilter.getStudyUid().trim() + LIKE))); - } - } - - /** - * Build criteria for serie uid - * - * @param criteriaBuilder CriteriaBuilder - * @param predicates Predicates to build - * @param pSerieUidOriginal Path of serie uid original - * @param pSerieUidToSend Path of serie uid to send - */ - private void buildCriteriaSerieUid( - CriteriaBuilder criteriaBuilder, - List predicates, - Path pSerieUidOriginal, - Path pSerieUidToSend) { - if (transferStatusFilter.getSerieUid() != null - && StringUtils.isNotBlank(transferStatusFilter.getSerieUid())) { - predicates.add( - criteriaBuilder.or( - criteriaBuilder.like( - pSerieUidOriginal, LIKE + transferStatusFilter.getSerieUid() + LIKE), - criteriaBuilder.like( - pSerieUidToSend, LIKE + transferStatusFilter.getSerieUid() + LIKE))); - } - } - - /** - * Build criteria for sop instance uid - * - * @param criteriaBuilder CriteriaBuilder - * @param predicates Predicates to build - * @param pSopInstanceUidOriginal Path of sop instance uid original - * @param pSopInstanceUidToSend Path of sop instance uid to send - */ - private void buildCriteriaSopInstanceUid( - CriteriaBuilder criteriaBuilder, - List predicates, - Path pSopInstanceUidOriginal, - Path pSopInstanceUidToSend) { - if (transferStatusFilter.getSopInstanceUid() != null - && StringUtils.isNotBlank(transferStatusFilter.getSopInstanceUid())) { - predicates.add( - criteriaBuilder.or( - criteriaBuilder.like( - pSopInstanceUidOriginal, LIKE + transferStatusFilter.getSopInstanceUid() + LIKE), - criteriaBuilder.like( - pSopInstanceUidToSend, LIKE + transferStatusFilter.getSopInstanceUid() + LIKE))); - } - } - - /** - * Build criteria for sent - * - * @param criteriaBuilder CriteriaBuilder - * @param predicates Predicates to build - * @param pSent Path of sent - */ - private void buildCriteriaSent( - CriteriaBuilder criteriaBuilder, List predicates, Path pSent) { - if (transferStatusFilter.getTransferStatusType() != null - && !Objects.equals(transferStatusFilter.getTransferStatusType(), TransferStatusType.ALL)) { - predicates.add( - criteriaBuilder.equal(pSent, transferStatusFilter.getTransferStatusType().getCode())); - } - } - - /** - * Build criteria for transfer date - * - * @param criteriaBuilder CriteriaBuilder - * @param predicates Predicates to build - * @param pTransferDate Path of transfer date - */ - private void buildCriteriaTransferDate( - CriteriaBuilder criteriaBuilder, - List predicates, - Path pTransferDate) { - if (transferStatusFilter.getStart() != null && transferStatusFilter.getEnd() == null) { - predicates.add( - criteriaBuilder.greaterThanOrEqualTo(pTransferDate, transferStatusFilter.getStart())); - } else if (transferStatusFilter.getStart() == null && transferStatusFilter.getEnd() != null) { - predicates.add( - criteriaBuilder.lessThanOrEqualTo(pTransferDate, transferStatusFilter.getEnd())); - } else if (transferStatusFilter.getStart() != null - && transferStatusFilter.getEnd() != null - && transferStatusFilter.getStart().isBefore(transferStatusFilter.getEnd())) { - predicates.add( - criteriaBuilder.between( - pTransferDate, transferStatusFilter.getStart(), transferStatusFilter.getEnd())); - } - } + @Serial + private static final long serialVersionUID = -939448741462690254L; + + // Like character + private static final String LIKE = "%"; + + // Criteria to look for + private final TransferStatusFilter transferStatusFilter; + + /** + * Constructor with filter + * @param transferStatusFilter Criteria to look for + */ + public TransferStatusSpecification(TransferStatusFilter transferStatusFilter) { + this.transferStatusFilter = transferStatusFilter; + } + + @Override + public Predicate toPredicate(Root root, CriteriaQuery query, + CriteriaBuilder criteriaBuilder) { + // Predicates to fill + List predicates = new ArrayList<>(); + + // Paths + // Study Uid + Path pStudyUidOriginal = root.get("studyUidOriginal"); + Path pStudyUidToSend = root.get("studyUidToSend"); + // Serie Uid + Path pSerieUidOriginal = root.get("serieUidOriginal"); + Path pSerieUidToSend = root.get("serieUidToSend"); + // Sop Instance Uid + Path pSopInstanceUidOriginal = root.get("sopInstanceUidOriginal"); + Path pSopInstanceUidToSend = root.get("sopInstanceUidToSend"); + // Status + Path pSent = root.get("sent"); + // Transfer date + Path pTransferDate = root.get("transferDate"); + + // Build criteria + if (transferStatusFilter != null) { + // Study Uid + buildCriteriaStudyUid(criteriaBuilder, predicates, pStudyUidOriginal, pStudyUidToSend); + // Serie Uid + buildCriteriaSerieUid(criteriaBuilder, predicates, pSerieUidOriginal, pSerieUidToSend); + // Sop Instance Uid + buildCriteriaSopInstanceUid(criteriaBuilder, predicates, pSopInstanceUidOriginal, pSopInstanceUidToSend); + // Sent + buildCriteriaSent(criteriaBuilder, predicates, pSent); + // Transfer Date + buildCriteriaTransferDate(criteriaBuilder, predicates, pTransferDate); + } + + return criteriaBuilder.and(predicates.toArray(new Predicate[] {})); + } + + /** + * Build criteria for study uid + * @param criteriaBuilder CriteriaBuilder + * @param predicates Predicates to build + * @param pStudyUidOriginal Path of study uid original + * @param pStudyUidToSend Path of study uid to send + */ + private void buildCriteriaStudyUid(CriteriaBuilder criteriaBuilder, List predicates, + Path pStudyUidOriginal, Path pStudyUidToSend) { + if (transferStatusFilter.getStudyUid() != null && StringUtils.isNotBlank(transferStatusFilter.getStudyUid())) { + predicates.add(criteriaBuilder.or( + criteriaBuilder.like(pStudyUidOriginal, LIKE + transferStatusFilter.getStudyUid().trim() + LIKE), + criteriaBuilder.like(pStudyUidToSend, LIKE + transferStatusFilter.getStudyUid().trim() + LIKE))); + } + } + + /** + * Build criteria for serie uid + * @param criteriaBuilder CriteriaBuilder + * @param predicates Predicates to build + * @param pSerieUidOriginal Path of serie uid original + * @param pSerieUidToSend Path of serie uid to send + */ + private void buildCriteriaSerieUid(CriteriaBuilder criteriaBuilder, List predicates, + Path pSerieUidOriginal, Path pSerieUidToSend) { + if (transferStatusFilter.getSerieUid() != null && StringUtils.isNotBlank(transferStatusFilter.getSerieUid())) { + predicates.add(criteriaBuilder.or( + criteriaBuilder.like(pSerieUidOriginal, LIKE + transferStatusFilter.getSerieUid() + LIKE), + criteriaBuilder.like(pSerieUidToSend, LIKE + transferStatusFilter.getSerieUid() + LIKE))); + } + } + + /** + * Build criteria for sop instance uid + * @param criteriaBuilder CriteriaBuilder + * @param predicates Predicates to build + * @param pSopInstanceUidOriginal Path of sop instance uid original + * @param pSopInstanceUidToSend Path of sop instance uid to send + */ + private void buildCriteriaSopInstanceUid(CriteriaBuilder criteriaBuilder, List predicates, + Path pSopInstanceUidOriginal, Path pSopInstanceUidToSend) { + if (transferStatusFilter.getSopInstanceUid() != null + && StringUtils.isNotBlank(transferStatusFilter.getSopInstanceUid())) { + predicates.add(criteriaBuilder.or( + criteriaBuilder.like(pSopInstanceUidOriginal, + LIKE + transferStatusFilter.getSopInstanceUid() + LIKE), + criteriaBuilder.like(pSopInstanceUidToSend, + LIKE + transferStatusFilter.getSopInstanceUid() + LIKE))); + } + } + + /** + * Build criteria for sent + * @param criteriaBuilder CriteriaBuilder + * @param predicates Predicates to build + * @param pSent Path of sent + */ + private void buildCriteriaSent(CriteriaBuilder criteriaBuilder, List predicates, Path pSent) { + if (transferStatusFilter.getTransferStatusType() != null + && !Objects.equals(transferStatusFilter.getTransferStatusType(), TransferStatusType.ALL)) { + predicates.add(criteriaBuilder.equal(pSent, transferStatusFilter.getTransferStatusType().getCode())); + } + } + + /** + * Build criteria for transfer date + * @param criteriaBuilder CriteriaBuilder + * @param predicates Predicates to build + * @param pTransferDate Path of transfer date + */ + private void buildCriteriaTransferDate(CriteriaBuilder criteriaBuilder, List predicates, + Path pTransferDate) { + if (transferStatusFilter.getStart() != null && transferStatusFilter.getEnd() == null) { + predicates.add(criteriaBuilder.greaterThanOrEqualTo(pTransferDate, transferStatusFilter.getStart())); + } + else if (transferStatusFilter.getStart() == null && transferStatusFilter.getEnd() != null) { + predicates.add(criteriaBuilder.lessThanOrEqualTo(pTransferDate, transferStatusFilter.getEnd())); + } + else if (transferStatusFilter.getStart() != null && transferStatusFilter.getEnd() != null + && transferStatusFilter.getStart().isBefore(transferStatusFilter.getEnd())) { + predicates.add(criteriaBuilder.between(pTransferDate, transferStatusFilter.getStart(), + transferStatusFilter.getEnd())); + } + } + } diff --git a/src/main/java/org/karnak/backend/data/validator/DestinationGroupSequenceProvider.java b/src/main/java/org/karnak/backend/data/validator/DestinationGroupSequenceProvider.java index 9bbd6a973..ca801e172 100644 --- a/src/main/java/org/karnak/backend/data/validator/DestinationGroupSequenceProvider.java +++ b/src/main/java/org/karnak/backend/data/validator/DestinationGroupSequenceProvider.java @@ -17,37 +17,42 @@ import org.karnak.backend.enums.DestinationType; /** - * @see - * https://stackoverflow.com/questions/27173960/jsr303-apply-all-validation-groups-defined-in-sequence + * @see https://stackoverflow.com/questions/27173960/jsr303-apply-all-validation-groups-defined-in-sequence */ -public class DestinationGroupSequenceProvider - implements DefaultGroupSequenceProvider { - - @Override - public List> getValidationGroups(DestinationEntity destinationEntity) { - if (destinationEntity != null) { - DestinationType type = destinationEntity.getDestinationType(); - if (type != null) { - switch (type) { - case dicom: - return TYPE_DICOM_GROUPS; - case stow: - return TYPE_STOW_GROUPS; - } - } - } - - return DEFAULT_GROUPS; - } - - public interface DestinationDicomGroup {} - - private static final List> DEFAULT_GROUPS = // - Collections.singletonList(DestinationEntity.class); - private static final List> TYPE_DICOM_GROUPS = // - Arrays.asList(DestinationEntity.class, DestinationDicomGroup.class); - private static final List> TYPE_STOW_GROUPS = // - Arrays.asList(DestinationEntity.class, DestinationStowGroup.class); - - public interface DestinationStowGroup {} +public class DestinationGroupSequenceProvider implements DefaultGroupSequenceProvider { + + @Override + public List> getValidationGroups(DestinationEntity destinationEntity) { + if (destinationEntity != null) { + DestinationType type = destinationEntity.getDestinationType(); + if (type != null) { + switch (type) { + case dicom: + return TYPE_DICOM_GROUPS; + case stow: + return TYPE_STOW_GROUPS; + } + } + } + + return DEFAULT_GROUPS; + } + + public interface DestinationDicomGroup { + + } + + private static final List> DEFAULT_GROUPS = // + Collections.singletonList(DestinationEntity.class); + + private static final List> TYPE_DICOM_GROUPS = // + Arrays.asList(DestinationEntity.class, DestinationDicomGroup.class); + + private static final List> TYPE_STOW_GROUPS = // + Arrays.asList(DestinationEntity.class, DestinationStowGroup.class); + + public interface DestinationStowGroup { + + } + } diff --git a/src/main/java/org/karnak/backend/dicom/DateTimeUtils.java b/src/main/java/org/karnak/backend/dicom/DateTimeUtils.java index 082c8f1cc..cfea65ee6 100644 --- a/src/main/java/org/karnak/backend/dicom/DateTimeUtils.java +++ b/src/main/java/org/karnak/backend/dicom/DateTimeUtils.java @@ -9,10 +9,22 @@ */ package org.karnak.backend.dicom; -import static java.time.temporal.ChronoField.*; +import static java.time.temporal.ChronoField.DAY_OF_MONTH; +import static java.time.temporal.ChronoField.HOUR_OF_DAY; +import static java.time.temporal.ChronoField.MINUTE_OF_HOUR; +import static java.time.temporal.ChronoField.MONTH_OF_YEAR; import static java.time.temporal.ChronoField.NANO_OF_SECOND; - -import java.time.*; +import static java.time.temporal.ChronoField.OFFSET_SECONDS; +import static java.time.temporal.ChronoField.SECOND_OF_MINUTE; +import static java.time.temporal.ChronoField.YEAR; + +import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatterBuilder; import java.time.format.FormatStyle; @@ -29,317 +41,267 @@ * @since Apr 2019 */ public class DateTimeUtils { - private static final Logger LOGGER = LoggerFactory.getLogger(DateTimeUtils.class); - - private static final DateTimeFormatter DA_PARSER = - new DateTimeFormatterBuilder() - .appendValue(YEAR, 4) - .optionalStart() - .appendLiteral('.') - .optionalEnd() - .appendValue(MONTH_OF_YEAR, 2) - .optionalStart() - .appendLiteral('.') - .optionalEnd() - .appendValue(DAY_OF_MONTH, 2) - .toFormatter(); - - private static final DateTimeFormatter DA_FORMATTER = - new DateTimeFormatterBuilder() - .appendValue(YEAR, 4) - .appendValue(MONTH_OF_YEAR, 2) - .appendValue(DAY_OF_MONTH, 2) - .toFormatter(); - - private static final DateTimeFormatter TM_PARSER = - new DateTimeFormatterBuilder() - .appendValue(HOUR_OF_DAY, 2) - .optionalStart() - .optionalStart() - .appendLiteral(':') - .optionalEnd() - .appendValue(MINUTE_OF_HOUR, 2) - .optionalStart() - .optionalStart() - .appendLiteral(':') - .optionalEnd() - .appendValue(SECOND_OF_MINUTE, 2) - .optionalStart() - .appendFraction(NANO_OF_SECOND, 0, 6, true) - .toFormatter(); - - private static final DateTimeFormatter TM_FORMATTER = - new DateTimeFormatterBuilder() - .appendValue(HOUR_OF_DAY, 2) - .appendValue(MINUTE_OF_HOUR, 2) - .appendValue(SECOND_OF_MINUTE, 2) - .appendFraction(NANO_OF_SECOND, 6, 6, true) - .toFormatter(); - - private static final DateTimeFormatter DT_PARSER = - new DateTimeFormatterBuilder() - .appendValue(YEAR, 4) - .optionalStart() - .appendValue(MONTH_OF_YEAR, 2) - .optionalStart() - .appendValue(DAY_OF_MONTH, 2) - .optionalStart() - .appendValue(HOUR_OF_DAY, 2) - .optionalStart() - .appendValue(MINUTE_OF_HOUR, 2) - .optionalStart() - .appendValue(SECOND_OF_MINUTE, 2) - .optionalStart() - .appendFraction(NANO_OF_SECOND, 0, 6, true) - .optionalEnd() - .optionalEnd() - .optionalEnd() - .optionalEnd() - .optionalEnd() - .optionalEnd() - .optionalStart() - .appendOffset("+HHMM", "+0000") - .toFormatter(); - - private static final DateTimeFormatter DT_FORMATTER = - new DateTimeFormatterBuilder() - .appendValue(YEAR, 4) - .appendValue(MONTH_OF_YEAR, 2) - .appendValue(DAY_OF_MONTH, 2) - .appendValue(HOUR_OF_DAY, 2) - .appendValue(MINUTE_OF_HOUR, 2) - .appendValue(SECOND_OF_MINUTE, 2) - .appendFraction(NANO_OF_SECOND, 6, 6, true) - .optionalStart() - .appendOffset("+HHMM", "+0000") - .toFormatter(); - - public static LocalDate parseDA(String value) { - return LocalDate.from(DA_PARSER.parse(value)); - } - - public static String formatDA(Temporal value) { - return DA_FORMATTER.format(value); - } - - public static LocalTime parseTM(String value) { - return LocalTime.from(TM_PARSER.parse(value)); - } - - public static LocalTime parseTMMax(String value) { - return parseTM(value).plusNanos(nanosToAdd(value)); - } - - public static String formatTM(Temporal value) { - return TM_FORMATTER.format(value); - } - - public static Temporal parseDT(String value) { - TemporalAccessor temporal = DT_PARSER.parse(value); - LocalDate date = - temporal.isSupported(DAY_OF_MONTH) - ? LocalDate.from(temporal) - : LocalDate.of(temporal.get(YEAR), getMonth(temporal), 1); - LocalTime time = temporal.isSupported(HOUR_OF_DAY) ? LocalTime.from(temporal) : LocalTime.MIN; - LocalDateTime dateTime = LocalDateTime.of(date, time); - return temporal.isSupported(OFFSET_SECONDS) - ? ZonedDateTime.of(dateTime, ZoneOffset.ofTotalSeconds(temporal.get(OFFSET_SECONDS))) - : dateTime; - } - - public static LocalDateTime dateTime(LocalDate date, LocalTime time) { - if (date == null) { - return null; - } - if (time == null) { - return date.atStartOfDay(); - } - return LocalDateTime.of(date, time); - } - - private static int getMonth(TemporalAccessor temporal) { - return temporal.isSupported(MONTH_OF_YEAR) ? temporal.get(MONTH_OF_YEAR) : 1; - } - - public static Temporal parseDTMax(String value) { - int length = lengthWithoutZone(value); - return length > 8 - ? parseDT(value).plus(nanosToAdd(length - 8), ChronoUnit.NANOS) - : parseDT(value).plus(1, yearsMonthsDays(length)).minus(1, ChronoUnit.NANOS); - } - - public static String formatDT(Temporal value) { - return DT_FORMATTER.format(value); - } - - public static String truncateTM(String value, int maxLength) { - if (maxLength < 2) throw new IllegalArgumentException("maxLength %d < 2" + maxLength); - - return truncate(value, value.length(), maxLength, 8); - } - - public static String truncateDT(String value, int maxLength) { - if (maxLength < 4) throw new IllegalArgumentException("maxLength %d < 4" + maxLength); - - int index = indexOfZone(value); - return index < 0 - ? truncate(value, value.length(), maxLength, 16) - : truncate(value, index, maxLength, 16) + value.substring(index); - } - - private static long nanosToAdd(String tm) { - int length = tm.length(); - int index = tm.lastIndexOf(':'); - if (index > 0) { - length--; - if (index > 4) length--; - } - return nanosToAdd(length); - } - - private static long nanosToAdd(int length) { - switch (length) { - case 2: - return 3599999999999L; - case 4: - return 59999999999L; - case 6: - case 7: - return 999999999L; - case 8: - return 99999999L; - case 9: - return 9999999L; - case 10: - return 999999L; - case 11: - return 99999L; - case 12: - return 9999L; - case 13: - return 999L; - } - throw new IllegalArgumentException("length: " + length); - } - - private static ChronoUnit yearsMonthsDays(int length) { - switch (length) { - case 4: - return ChronoUnit.YEARS; - case 6: - return ChronoUnit.MONTHS; - case 8: - return ChronoUnit.DAYS; - } - throw new IllegalArgumentException("length: " + length); - } - - private static int lengthWithoutZone(String value) { - int index = indexOfZone(value); - return index < 0 ? value.length() : index; - } - - private static int indexOfZone(String value) { - int index = value.length() - 5; - return index >= 4 && isSign(value.charAt(index)) ? index : -1; - } - - private static boolean isSign(char ch) { - return ch == '+' || ch == '-'; - } - - private static String truncate(String value, int length, int maxLength, int fractionPos) { - return value.substring(0, adjustMaxLength(Math.min(length, maxLength), fractionPos)); - } - - private static int adjustMaxLength(int maxLength, int fractionPos) { - return maxLength < fractionPos ? maxLength & ~1 : maxLength; - } - - /** - * Conversion from old to new Time API - * - * @author Nicolas Roduit - */ - private static final DateTimeFormatter defaultDateFormatter = - DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM); - - private static final DateTimeFormatter defaultTimeFormatter = - DateTimeFormatter.ofLocalizedTime(FormatStyle.MEDIUM); - private static final DateTimeFormatter defaultDateTimeFormatter = - DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM); - - /** - * Convert date or time object to display date in String with FormatStyle.MEDIUM - * - * @param date - * @return the time to display with FormatStyle.MEDIUM - */ - public static String formatDateTime(TemporalAccessor date) { - if (date instanceof LocalDate) { - return defaultDateFormatter.format(date); - } else if (date instanceof LocalTime) { - return defaultTimeFormatter.format(date); - } else if (date instanceof LocalDateTime || date instanceof ZonedDateTime) { - return defaultDateTimeFormatter.format(date); - } else if (date instanceof Instant) { - return defaultDateTimeFormatter.format(((Instant) date).atZone(ZoneId.systemDefault())); - } - return ""; - } - - public static LocalDate toLocalDate(Date date) { - if (date != null) { - try { - LocalDateTime datetime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()); - return datetime.toLocalDate(); - } catch (Exception e) { - LOGGER.error("Date conversion", e); - } - } - return null; - } - - public static LocalTime toLocalTime(Date date) { - if (date != null) { - try { - LocalDateTime datetime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()); - return datetime.toLocalTime(); - } catch (Exception e) { - LOGGER.error("Time conversion", e); - } - } - return null; - } - - public static LocalDateTime toLocalDateTime(Date date) { - if (date != null) { - try { - return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()); - } catch (Exception e) { - LOGGER.error("DateTime conversion", e); - } - } - return null; - } - - public static Date dateTime(Date date, Date time) { - if (time == null) { - return date; - } else if (date == null) { - return time; - } - Calendar calendarA = Calendar.getInstance(); - calendarA.setTime(date); - - Calendar calendarB = Calendar.getInstance(); - calendarB.setTime(time); - - calendarA.set(Calendar.HOUR_OF_DAY, calendarB.get(Calendar.HOUR_OF_DAY)); - calendarA.set(Calendar.MINUTE, calendarB.get(Calendar.MINUTE)); - calendarA.set(Calendar.SECOND, calendarB.get(Calendar.SECOND)); - calendarA.set(Calendar.MILLISECOND, calendarB.get(Calendar.MILLISECOND)); - - return calendarA.getTime(); - } + + private static final Logger LOGGER = LoggerFactory.getLogger(DateTimeUtils.class); + + private static final DateTimeFormatter DA_PARSER = new DateTimeFormatterBuilder().appendValue(YEAR, 4) + .optionalStart().appendLiteral('.').optionalEnd().appendValue(MONTH_OF_YEAR, 2).optionalStart() + .appendLiteral('.').optionalEnd().appendValue(DAY_OF_MONTH, 2).toFormatter(); + + private static final DateTimeFormatter DA_FORMATTER = new DateTimeFormatterBuilder().appendValue(YEAR, 4) + .appendValue(MONTH_OF_YEAR, 2).appendValue(DAY_OF_MONTH, 2).toFormatter(); + + private static final DateTimeFormatter TM_PARSER = new DateTimeFormatterBuilder().appendValue(HOUR_OF_DAY, 2) + .optionalStart().optionalStart().appendLiteral(':').optionalEnd().appendValue(MINUTE_OF_HOUR, 2) + .optionalStart().optionalStart().appendLiteral(':').optionalEnd().appendValue(SECOND_OF_MINUTE, 2) + .optionalStart().appendFraction(NANO_OF_SECOND, 0, 6, true).toFormatter(); + + private static final DateTimeFormatter TM_FORMATTER = new DateTimeFormatterBuilder().appendValue(HOUR_OF_DAY, 2) + .appendValue(MINUTE_OF_HOUR, 2).appendValue(SECOND_OF_MINUTE, 2).appendFraction(NANO_OF_SECOND, 6, 6, true) + .toFormatter(); + + private static final DateTimeFormatter DT_PARSER = new DateTimeFormatterBuilder().appendValue(YEAR, 4) + .optionalStart().appendValue(MONTH_OF_YEAR, 2).optionalStart().appendValue(DAY_OF_MONTH, 2).optionalStart() + .appendValue(HOUR_OF_DAY, 2).optionalStart().appendValue(MINUTE_OF_HOUR, 2).optionalStart() + .appendValue(SECOND_OF_MINUTE, 2).optionalStart().appendFraction(NANO_OF_SECOND, 0, 6, true).optionalEnd() + .optionalEnd().optionalEnd().optionalEnd().optionalEnd().optionalEnd().optionalStart() + .appendOffset("+HHMM", "+0000").toFormatter(); + + private static final DateTimeFormatter DT_FORMATTER = new DateTimeFormatterBuilder().appendValue(YEAR, 4) + .appendValue(MONTH_OF_YEAR, 2).appendValue(DAY_OF_MONTH, 2).appendValue(HOUR_OF_DAY, 2) + .appendValue(MINUTE_OF_HOUR, 2).appendValue(SECOND_OF_MINUTE, 2).appendFraction(NANO_OF_SECOND, 6, 6, true) + .optionalStart().appendOffset("+HHMM", "+0000").toFormatter(); + + public static LocalDate parseDA(String value) { + return LocalDate.from(DA_PARSER.parse(value)); + } + + public static String formatDA(Temporal value) { + return DA_FORMATTER.format(value); + } + + public static LocalTime parseTM(String value) { + return LocalTime.from(TM_PARSER.parse(value)); + } + + public static LocalTime parseTMMax(String value) { + return parseTM(value).plusNanos(nanosToAdd(value)); + } + + public static String formatTM(Temporal value) { + return TM_FORMATTER.format(value); + } + + public static Temporal parseDT(String value) { + TemporalAccessor temporal = DT_PARSER.parse(value); + LocalDate date = temporal.isSupported(DAY_OF_MONTH) ? LocalDate.from(temporal) + : LocalDate.of(temporal.get(YEAR), getMonth(temporal), 1); + LocalTime time = temporal.isSupported(HOUR_OF_DAY) ? LocalTime.from(temporal) : LocalTime.MIN; + LocalDateTime dateTime = LocalDateTime.of(date, time); + return temporal.isSupported(OFFSET_SECONDS) + ? ZonedDateTime.of(dateTime, ZoneOffset.ofTotalSeconds(temporal.get(OFFSET_SECONDS))) : dateTime; + } + + public static LocalDateTime dateTime(LocalDate date, LocalTime time) { + if (date == null) { + return null; + } + if (time == null) { + return date.atStartOfDay(); + } + return LocalDateTime.of(date, time); + } + + private static int getMonth(TemporalAccessor temporal) { + return temporal.isSupported(MONTH_OF_YEAR) ? temporal.get(MONTH_OF_YEAR) : 1; + } + + public static Temporal parseDTMax(String value) { + int length = lengthWithoutZone(value); + return length > 8 ? parseDT(value).plus(nanosToAdd(length - 8), ChronoUnit.NANOS) + : parseDT(value).plus(1, yearsMonthsDays(length)).minus(1, ChronoUnit.NANOS); + } + + public static String formatDT(Temporal value) { + return DT_FORMATTER.format(value); + } + + public static String truncateTM(String value, int maxLength) { + if (maxLength < 2) + throw new IllegalArgumentException("maxLength %d < 2" + maxLength); + + return truncate(value, value.length(), maxLength, 8); + } + + public static String truncateDT(String value, int maxLength) { + if (maxLength < 4) + throw new IllegalArgumentException("maxLength %d < 4" + maxLength); + + int index = indexOfZone(value); + return index < 0 ? truncate(value, value.length(), maxLength, 16) + : truncate(value, index, maxLength, 16) + value.substring(index); + } + + private static long nanosToAdd(String tm) { + int length = tm.length(); + int index = tm.lastIndexOf(':'); + if (index > 0) { + length--; + if (index > 4) + length--; + } + return nanosToAdd(length); + } + + private static long nanosToAdd(int length) { + switch (length) { + case 2: + return 3599999999999L; + case 4: + return 59999999999L; + case 6: + case 7: + return 999999999L; + case 8: + return 99999999L; + case 9: + return 9999999L; + case 10: + return 999999L; + case 11: + return 99999L; + case 12: + return 9999L; + case 13: + return 999L; + } + throw new IllegalArgumentException("length: " + length); + } + + private static ChronoUnit yearsMonthsDays(int length) { + switch (length) { + case 4: + return ChronoUnit.YEARS; + case 6: + return ChronoUnit.MONTHS; + case 8: + return ChronoUnit.DAYS; + } + throw new IllegalArgumentException("length: " + length); + } + + private static int lengthWithoutZone(String value) { + int index = indexOfZone(value); + return index < 0 ? value.length() : index; + } + + private static int indexOfZone(String value) { + int index = value.length() - 5; + return index >= 4 && isSign(value.charAt(index)) ? index : -1; + } + + private static boolean isSign(char ch) { + return ch == '+' || ch == '-'; + } + + private static String truncate(String value, int length, int maxLength, int fractionPos) { + return value.substring(0, adjustMaxLength(Math.min(length, maxLength), fractionPos)); + } + + private static int adjustMaxLength(int maxLength, int fractionPos) { + return maxLength < fractionPos ? maxLength & ~1 : maxLength; + } + + /** + * Conversion from old to new Time API + * + * @author Nicolas Roduit + */ + private static final DateTimeFormatter defaultDateFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM); + + private static final DateTimeFormatter defaultTimeFormatter = DateTimeFormatter.ofLocalizedTime(FormatStyle.MEDIUM); + + private static final DateTimeFormatter defaultDateTimeFormatter = DateTimeFormatter + .ofLocalizedDateTime(FormatStyle.MEDIUM); + + /** + * Convert date or time object to display date in String with FormatStyle.MEDIUM + * @param date + * @return the time to display with FormatStyle.MEDIUM + */ + public static String formatDateTime(TemporalAccessor date) { + if (date instanceof LocalDate) { + return defaultDateFormatter.format(date); + } + else if (date instanceof LocalTime) { + return defaultTimeFormatter.format(date); + } + else if (date instanceof LocalDateTime || date instanceof ZonedDateTime) { + return defaultDateTimeFormatter.format(date); + } + else if (date instanceof Instant) { + return defaultDateTimeFormatter.format(((Instant) date).atZone(ZoneId.systemDefault())); + } + return ""; + } + + public static LocalDate toLocalDate(Date date) { + if (date != null) { + try { + LocalDateTime datetime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()); + return datetime.toLocalDate(); + } + catch (Exception e) { + LOGGER.error("Date conversion", e); + } + } + return null; + } + + public static LocalTime toLocalTime(Date date) { + if (date != null) { + try { + LocalDateTime datetime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()); + return datetime.toLocalTime(); + } + catch (Exception e) { + LOGGER.error("Time conversion", e); + } + } + return null; + } + + public static LocalDateTime toLocalDateTime(Date date) { + if (date != null) { + try { + return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()); + } + catch (Exception e) { + LOGGER.error("DateTime conversion", e); + } + } + return null; + } + + public static Date dateTime(Date date, Date time) { + if (time == null) { + return date; + } + else if (date == null) { + return time; + } + Calendar calendarA = Calendar.getInstance(); + calendarA.setTime(date); + + Calendar calendarB = Calendar.getInstance(); + calendarB.setTime(time); + + calendarA.set(Calendar.HOUR_OF_DAY, calendarB.get(Calendar.HOUR_OF_DAY)); + calendarA.set(Calendar.MINUTE, calendarB.get(Calendar.MINUTE)); + calendarA.set(Calendar.SECOND, calendarB.get(Calendar.SECOND)); + calendarA.set(Calendar.MILLISECOND, calendarB.get(Calendar.MILLISECOND)); + + return calendarA.getTime(); + } + } diff --git a/src/main/java/org/karnak/backend/dicom/Defacer.java b/src/main/java/org/karnak/backend/dicom/Defacer.java index 88aaa9be2..455199d09 100644 --- a/src/main/java/org/karnak/backend/dicom/Defacer.java +++ b/src/main/java/org/karnak/backend/dicom/Defacer.java @@ -26,162 +26,150 @@ public class Defacer { - public static final String APPLY_DEFACING = "defacing"; - - private Defacer() {} - - public static PlanarImage apply(Attributes attributes, PlanarImage image) { - PlanarImage faceDetectionImg = faceDetection(attributes, image); - PlanarImage randPxlLineImg = addRandPxlLine(image, faceDetectionImg, attributes); - PlanarImage mergedImg = mergeImg(image, randPxlLineImg, faceDetectionImg); - return blurImg(mergedImg, faceDetectionImg); - } - - public static PlanarImage filterBySkin(Attributes attributes, PlanarImage srcImg) { - ImageCV skinImg = new ImageCV(); - srcImg.toMat().copyTo(skinImg); - - MinMaxLocResult minMaxLutFaceDetectionImg = ImageProcessor.findMinMaxValues(skinImg); - - Imgproc.threshold( - skinImg.toImageCV(), - skinImg.toMat(), - DefacingUtil.hounsfieldToPxlValue(attributes, 100), - minMaxLutFaceDetectionImg.maxVal, - Imgproc.THRESH_TOZERO); - Imgproc.threshold( - skinImg.toImageCV(), - skinImg.toMat(), - DefacingUtil.hounsfieldToPxlValue(attributes, 300), - minMaxLutFaceDetectionImg.maxVal, - Imgproc.THRESH_TOZERO_INV); - return skinImg; - } - - public static PlanarImage faceDetection(Attributes attributes, PlanarImage srcImg) { - ImageCV faceDetectionImg = new ImageCV(); - srcImg.toMat().copyTo(faceDetectionImg); - - MinMaxLocResult minMaxLocResult = ImageProcessor.findMinMaxValues(faceDetectionImg.toMat()); - - Imgproc.threshold( - faceDetectionImg.toImageCV(), - faceDetectionImg.toMat(), - DefacingUtil.hounsfieldToPxlValue(attributes, -500), - minMaxLocResult.maxVal, - Imgproc.THRESH_BINARY); - - // ERODE - Mat kernel = new Mat(); - int kernelSize = 5; - Mat ones = Mat.ones(kernelSize, kernelSize, CvType.CV_32F); - Core.multiply(ones, new Scalar(1 / (double) (kernelSize * kernelSize)), kernel); - Imgproc.erode(faceDetectionImg.toImageCV(), faceDetectionImg.toMat(), kernel); - - // RESCALE 8BIT - faceDetectionImg = DefacingUtil.transformToByte(faceDetectionImg).toImageCV(); - - // CANNY DETECT CONTOUR - Imgproc.Canny(faceDetectionImg.toImageCV(), faceDetectionImg.toMat(), 240, 260); - - // DRAW BLACK RECT 1/3 - int rectProportion = (int) (faceDetectionImg.height() / 2.9); - Rect rect = new Rect(0, rectProportion, faceDetectionImg.width(), faceDetectionImg.height()); - Imgproc.rectangle(faceDetectionImg.toImageCV(), rect, new Scalar(255), Imgproc.FILLED); - - for (int x = 0; x < faceDetectionImg.width(); x++) { - for (int y = 0; y < faceDetectionImg.height(); y++) { - if (faceDetectionImg.toMat().get(y, x)[0] == 255) { - Imgproc.line( - faceDetectionImg.toImageCV(), - new Point(x, y + 1.0), - new Point(x, faceDetectionImg.height()), - new Scalar(0)); - break; - } - } - } - - return faceDetectionImg; - } - - public static PlanarImage addRandPxlLine( - PlanarImage srcImg, PlanarImage faceDetectImg, Attributes attributes) { - ImageCV randPxlLineImg = new ImageCV(); - srcImg.toMat().copyTo(randPxlLineImg); - double pixelSpacing = attributes.getDouble(Tag.PixelSpacing, 0.5); - int minThicknessSkin = (int) (1 / pixelSpacing); // 1mm - int maxThicknessSkin = (int) (3 / pixelSpacing); // 3mm - // DRAW A LINE WITH RANDOM VALUE WHEN FACE DETECTED - int yOffsetRand = 1; - // scan the image from left to right and bottom to top until the face is detected in Y - for (int x = 0; x < faceDetectImg.width(); x++) { - boolean faceDetected = false; - int yFaceDetected = 0; - int thicknessSkin = DefacingUtil.randomY(minThicknessSkin, maxThicknessSkin, 1); - int margeY = maxThicknessSkin * 2; - - for (int y = faceDetectImg.height() - 1; y > 0; y--) { - double faceDetectPixelValue = faceDetectImg.toMat().get(y, x)[0]; - if (faceDetectPixelValue == 255.0) { - faceDetected = true; - yFaceDetected = y; - } - - if (faceDetected) { - // Put random color after the face detection - int minY = yFaceDetected + yOffsetRand; - int maxY = yFaceDetected + yOffsetRand + margeY; - double randomPixelColor = DefacingUtil.pickRndYPxlColor(x, minY, maxY, srcImg); - randPxlLineImg.toMat().put(y + thicknessSkin, x, randomPixelColor); - } else { - randPxlLineImg.toMat().put(y, x, 0.0); - } - } - } - return randPxlLineImg; - } - - public static PlanarImage blurImg(PlanarImage srcImg, PlanarImage faceDetectImg) { - ImageCV bluredImgRandPxlLine = new ImageCV(); - srcImg.toMat().copyTo(bluredImgRandPxlLine); - Imgproc.blur(bluredImgRandPxlLine.toImageCV(), bluredImgRandPxlLine.toMat(), new Size(5, 5)); - - int marginBlurSkin = 20; - - for (int x = 0; x < faceDetectImg.width(); x++) { - boolean faceDetected = true; - int yNoBlurImg = 0; - for (int y = 0; y < faceDetectImg.height(); y++) { - if (faceDetectImg.toMat().get(y, x)[0] != 0.0) { - faceDetected = false; - yNoBlurImg = y + marginBlurSkin; - } - - if (!faceDetected) { - bluredImgRandPxlLine.toMat().put(yNoBlurImg, x, srcImg.toMat().get(yNoBlurImg, x)[0]); - } - } - } - - return bluredImgRandPxlLine; - } - - public static PlanarImage mergeImg( - PlanarImage srcImg, PlanarImage randPxlLineImg, PlanarImage faceDetectImg) { - // MERGE IMAGE SRC AND RAND PIXEL LINE - ImageCV newImg = new ImageCV(); - srcImg.toMat().copyTo(newImg); - - for (int x = 0; x < faceDetectImg.width(); x++) { - for (int y = faceDetectImg.height() - 1; y > 0; y--) { - if (randPxlLineImg.toMat().get(y, x)[0] != 0.0) { - newImg.toMat().put(y, x, randPxlLineImg.toMat().get(y, x)[0]); - } else { - newImg.toMat().put(y, x, srcImg.toMat().get(y, x)[0]); - } - } - } - return newImg; - } + public static final String APPLY_DEFACING = "defacing"; + + private Defacer() { + } + + public static PlanarImage apply(Attributes attributes, PlanarImage image) { + PlanarImage faceDetectionImg = faceDetection(attributes, image); + PlanarImage randPxlLineImg = addRandPxlLine(image, faceDetectionImg, attributes); + PlanarImage mergedImg = mergeImg(image, randPxlLineImg, faceDetectionImg); + return blurImg(mergedImg, faceDetectionImg); + } + + public static PlanarImage filterBySkin(Attributes attributes, PlanarImage srcImg) { + ImageCV skinImg = new ImageCV(); + srcImg.toMat().copyTo(skinImg); + + MinMaxLocResult minMaxLutFaceDetectionImg = ImageProcessor.findMinMaxValues(skinImg); + + Imgproc.threshold(skinImg.toImageCV(), skinImg.toMat(), DefacingUtil.hounsfieldToPxlValue(attributes, 100), + minMaxLutFaceDetectionImg.maxVal, Imgproc.THRESH_TOZERO); + Imgproc.threshold(skinImg.toImageCV(), skinImg.toMat(), DefacingUtil.hounsfieldToPxlValue(attributes, 300), + minMaxLutFaceDetectionImg.maxVal, Imgproc.THRESH_TOZERO_INV); + return skinImg; + } + + public static PlanarImage faceDetection(Attributes attributes, PlanarImage srcImg) { + ImageCV faceDetectionImg = new ImageCV(); + srcImg.toMat().copyTo(faceDetectionImg); + + MinMaxLocResult minMaxLocResult = ImageProcessor.findMinMaxValues(faceDetectionImg.toMat()); + + Imgproc.threshold(faceDetectionImg.toImageCV(), faceDetectionImg.toMat(), + DefacingUtil.hounsfieldToPxlValue(attributes, -500), minMaxLocResult.maxVal, Imgproc.THRESH_BINARY); + + // ERODE + Mat kernel = new Mat(); + int kernelSize = 5; + Mat ones = Mat.ones(kernelSize, kernelSize, CvType.CV_32F); + Core.multiply(ones, new Scalar(1 / (double) (kernelSize * kernelSize)), kernel); + Imgproc.erode(faceDetectionImg.toImageCV(), faceDetectionImg.toMat(), kernel); + + // RESCALE 8BIT + faceDetectionImg = DefacingUtil.transformToByte(faceDetectionImg).toImageCV(); + + // CANNY DETECT CONTOUR + Imgproc.Canny(faceDetectionImg.toImageCV(), faceDetectionImg.toMat(), 240, 260); + + // DRAW BLACK RECT 1/3 + int rectProportion = (int) (faceDetectionImg.height() / 2.9); + Rect rect = new Rect(0, rectProportion, faceDetectionImg.width(), faceDetectionImg.height()); + Imgproc.rectangle(faceDetectionImg.toImageCV(), rect, new Scalar(255), Imgproc.FILLED); + + for (int x = 0; x < faceDetectionImg.width(); x++) { + for (int y = 0; y < faceDetectionImg.height(); y++) { + if (faceDetectionImg.toMat().get(y, x)[0] == 255) { + Imgproc.line(faceDetectionImg.toImageCV(), new Point(x, y + 1.0), + new Point(x, faceDetectionImg.height()), new Scalar(0)); + break; + } + } + } + + return faceDetectionImg; + } + + public static PlanarImage addRandPxlLine(PlanarImage srcImg, PlanarImage faceDetectImg, Attributes attributes) { + ImageCV randPxlLineImg = new ImageCV(); + srcImg.toMat().copyTo(randPxlLineImg); + double pixelSpacing = attributes.getDouble(Tag.PixelSpacing, 0.5); + int minThicknessSkin = (int) (1 / pixelSpacing); // 1mm + int maxThicknessSkin = (int) (3 / pixelSpacing); // 3mm + // DRAW A LINE WITH RANDOM VALUE WHEN FACE DETECTED + int yOffsetRand = 1; + // scan the image from left to right and bottom to top until the face is detected + // in Y + for (int x = 0; x < faceDetectImg.width(); x++) { + boolean faceDetected = false; + int yFaceDetected = 0; + int thicknessSkin = DefacingUtil.randomY(minThicknessSkin, maxThicknessSkin, 1); + int margeY = maxThicknessSkin * 2; + + for (int y = faceDetectImg.height() - 1; y > 0; y--) { + double faceDetectPixelValue = faceDetectImg.toMat().get(y, x)[0]; + if (faceDetectPixelValue == 255.0) { + faceDetected = true; + yFaceDetected = y; + } + + if (faceDetected) { + // Put random color after the face detection + int minY = yFaceDetected + yOffsetRand; + int maxY = yFaceDetected + yOffsetRand + margeY; + double randomPixelColor = DefacingUtil.pickRndYPxlColor(x, minY, maxY, srcImg); + randPxlLineImg.toMat().put(y + thicknessSkin, x, randomPixelColor); + } + else { + randPxlLineImg.toMat().put(y, x, 0.0); + } + } + } + return randPxlLineImg; + } + + public static PlanarImage blurImg(PlanarImage srcImg, PlanarImage faceDetectImg) { + ImageCV bluredImgRandPxlLine = new ImageCV(); + srcImg.toMat().copyTo(bluredImgRandPxlLine); + Imgproc.blur(bluredImgRandPxlLine.toImageCV(), bluredImgRandPxlLine.toMat(), new Size(5, 5)); + + int marginBlurSkin = 20; + + for (int x = 0; x < faceDetectImg.width(); x++) { + boolean faceDetected = true; + int yNoBlurImg = 0; + for (int y = 0; y < faceDetectImg.height(); y++) { + if (faceDetectImg.toMat().get(y, x)[0] != 0.0) { + faceDetected = false; + yNoBlurImg = y + marginBlurSkin; + } + + if (!faceDetected) { + bluredImgRandPxlLine.toMat().put(yNoBlurImg, x, srcImg.toMat().get(yNoBlurImg, x)[0]); + } + } + } + + return bluredImgRandPxlLine; + } + + public static PlanarImage mergeImg(PlanarImage srcImg, PlanarImage randPxlLineImg, PlanarImage faceDetectImg) { + // MERGE IMAGE SRC AND RAND PIXEL LINE + ImageCV newImg = new ImageCV(); + srcImg.toMat().copyTo(newImg); + + for (int x = 0; x < faceDetectImg.width(); x++) { + for (int y = faceDetectImg.height() - 1; y > 0; y--) { + if (randPxlLineImg.toMat().get(y, x)[0] != 0.0) { + newImg.toMat().put(y, x, randPxlLineImg.toMat().get(y, x)[0]); + } + else { + newImg.toMat().put(y, x, srcImg.toMat().get(y, x)[0]); + } + } + } + return newImg; + } + } diff --git a/src/main/java/org/karnak/backend/dicom/DefacingUtil.java b/src/main/java/org/karnak/backend/dicom/DefacingUtil.java index 495b8f14a..61a4b1914 100644 --- a/src/main/java/org/karnak/backend/dicom/DefacingUtil.java +++ b/src/main/java/org/karnak/backend/dicom/DefacingUtil.java @@ -19,102 +19,100 @@ public class DefacingUtil { - private DefacingUtil() {} - - public static int randomY(int minY, int maxY, int bound) { - SecureRandom random = new SecureRandom(); - return (int) Math.floor(random.nextDouble() * (maxY - minY + bound) + minY); - } - - public static double pickRndYPxlColor(int xInit, int minY, int maxY, PlanarImage imgToPick) { - int yRand = DefacingUtil.randomY(minY, maxY, 1); - return imgToPick.toMat().get(yRand, xInit)[0]; - } - - public static double pickRndYPxlColorConvolution( - int xInit, int minY, int maxY, PlanarImage imgToPick) { - int yRand = DefacingUtil.randomY(minY, maxY, 1); - int size = 5; - double mean = 0; - int sum = 0; - int imgWidth = imgToPick.width(); - int imgHeight = imgToPick.height(); - - // convolution - for (int x = xInit - (size / 2); x < xInit + (size / 2) + 1; x++) { - for (int y = yRand; y < yRand + size + 1; y++) { - int xPickColor = checkBoundsOfImageX(x, imgWidth); - int yPickColor = checkBoundsOfImageY(y, imgHeight); - double color = imgToPick.toMat().get(yPickColor, xPickColor)[0]; - - mean = mean + color; - sum++; - } - } - if (sum != 0) { - return mean / sum; - } - return mean; - } - - public static int checkBoundsOfImageX(int x, int imgWidth) { - if (x < 0) { - return 0; - } - if (x >= imgWidth) { - return imgWidth - 1; - } - return x; - } - - public static int checkBoundsOfImageY(int y, int imgHeight) { - if (y < 0) { - return 0; - } - if (y >= imgHeight) { - return imgHeight - 1; - } - return y; - } - - public static PlanarImage transformToByte(PlanarImage srcImg) { - ImageCV imgTransform = new ImageCV(); - srcImg.toMat().copyTo(imgTransform); - - MinMaxLocResult minMaxLocResult = ImageProcessor.findMinMaxValues(imgTransform.toMat()); - double min = minMaxLocResult.minVal; - double max = minMaxLocResult.maxVal; - double slope = 255.0 / (max - min); - double yint = 255.0 - slope * max; - imgTransform = ImageProcessor.rescaleToByte(imgTransform.toImageCV(), slope, yint); - return imgTransform; - } - - public static double hounsfieldToPxlValue(Attributes attributes, double hounsfield) { - double intercept = attributes.getDouble(Tag.RescaleIntercept, 0); - double slope = attributes.getDouble(Tag.RescaleSlope, 1.0); - return (hounsfield - intercept) / slope; - } - - public static PlanarImage rescaleForVisualizing( - PlanarImage srcImg, Double contrast, Double brigtness) { - ImageCV imageForVisualizing = new ImageCV(); - srcImg.toMat().copyTo(imageForVisualizing); - PlanarImage transformImg = transformToByte(imageForVisualizing); - transformImg = - ImageProcessor.rescaleToByte(transformImg.toImageCV(), contrast / 100.0, brigtness); - return transformImg; - } - - public static boolean isCT(Attributes attributes) { - String sopClassUID = attributes.getString(Tag.SOPClassUID); - return (sopClassUID + ".").startsWith("1.2.840.10008.5.1.4.1.1.2."); - } - - public static boolean isAxial(Attributes attributes) { - double[] vector = attributes.getDoubles(Tag.ImageOrientationPatient); - ImageOrientation.Label label = - ImageOrientation.makeImageOrientationLabelFromImageOrientationPatient(vector); - return label.equals(ImageOrientation.Label.AXIAL); - } + private DefacingUtil() { + } + + public static int randomY(int minY, int maxY, int bound) { + SecureRandom random = new SecureRandom(); + return (int) Math.floor(random.nextDouble() * (maxY - minY + bound) + minY); + } + + public static double pickRndYPxlColor(int xInit, int minY, int maxY, PlanarImage imgToPick) { + int yRand = DefacingUtil.randomY(minY, maxY, 1); + return imgToPick.toMat().get(yRand, xInit)[0]; + } + + public static double pickRndYPxlColorConvolution(int xInit, int minY, int maxY, PlanarImage imgToPick) { + int yRand = DefacingUtil.randomY(minY, maxY, 1); + int size = 5; + double mean = 0; + int sum = 0; + int imgWidth = imgToPick.width(); + int imgHeight = imgToPick.height(); + + // convolution + for (int x = xInit - (size / 2); x < xInit + (size / 2) + 1; x++) { + for (int y = yRand; y < yRand + size + 1; y++) { + int xPickColor = checkBoundsOfImageX(x, imgWidth); + int yPickColor = checkBoundsOfImageY(y, imgHeight); + double color = imgToPick.toMat().get(yPickColor, xPickColor)[0]; + + mean = mean + color; + sum++; + } + } + if (sum != 0) { + return mean / sum; + } + return mean; + } + + public static int checkBoundsOfImageX(int x, int imgWidth) { + if (x < 0) { + return 0; + } + if (x >= imgWidth) { + return imgWidth - 1; + } + return x; + } + + public static int checkBoundsOfImageY(int y, int imgHeight) { + if (y < 0) { + return 0; + } + if (y >= imgHeight) { + return imgHeight - 1; + } + return y; + } + + public static PlanarImage transformToByte(PlanarImage srcImg) { + ImageCV imgTransform = new ImageCV(); + srcImg.toMat().copyTo(imgTransform); + + MinMaxLocResult minMaxLocResult = ImageProcessor.findMinMaxValues(imgTransform.toMat()); + double min = minMaxLocResult.minVal; + double max = minMaxLocResult.maxVal; + double slope = 255.0 / (max - min); + double yint = 255.0 - slope * max; + imgTransform = ImageProcessor.rescaleToByte(imgTransform.toImageCV(), slope, yint); + return imgTransform; + } + + public static double hounsfieldToPxlValue(Attributes attributes, double hounsfield) { + double intercept = attributes.getDouble(Tag.RescaleIntercept, 0); + double slope = attributes.getDouble(Tag.RescaleSlope, 1.0); + return (hounsfield - intercept) / slope; + } + + public static PlanarImage rescaleForVisualizing(PlanarImage srcImg, Double contrast, Double brigtness) { + ImageCV imageForVisualizing = new ImageCV(); + srcImg.toMat().copyTo(imageForVisualizing); + PlanarImage transformImg = transformToByte(imageForVisualizing); + transformImg = ImageProcessor.rescaleToByte(transformImg.toImageCV(), contrast / 100.0, brigtness); + return transformImg; + } + + public static boolean isCT(Attributes attributes) { + String sopClassUID = attributes.getString(Tag.SOPClassUID); + return (sopClassUID + ".").startsWith("1.2.840.10008.5.1.4.1.1.2."); + } + + public static boolean isAxial(Attributes attributes) { + double[] vector = attributes.getDoubles(Tag.ImageOrientationPatient); + ImageOrientation.Label label = ImageOrientation.makeImageOrientationLabelFromImageOrientationPatient(vector); + return label.equals(ImageOrientation.Label.AXIAL); + } + } diff --git a/src/main/java/org/karnak/backend/dicom/DicomForwardDestination.java b/src/main/java/org/karnak/backend/dicom/DicomForwardDestination.java index fb89e6056..317858552 100644 --- a/src/main/java/org/karnak/backend/dicom/DicomForwardDestination.java +++ b/src/main/java/org/karnak/backend/dicom/DicomForwardDestination.java @@ -21,121 +21,99 @@ public class DicomForwardDestination extends ForwardDestination { - private final StoreFromStreamSCU streamSCU; - private final DeviceOpService streamSCUService; - private final boolean useDestinationAetForKeyMap; - - private final ForwardDicomNode callingNode; - private final DicomNode destinationNode; - - public DicomForwardDestination(ForwardDicomNode fwdNode, DicomNode destinationNode) - throws IOException { - this(null, fwdNode, destinationNode, null); - } - - public DicomForwardDestination( - AdvancedParams forwardParams, ForwardDicomNode fwdNode, DicomNode destinationNode) - throws IOException { - this(forwardParams, fwdNode, destinationNode, null); - } - - public DicomForwardDestination( - AdvancedParams forwardParams, - ForwardDicomNode fwdNode, - DicomNode destinationNode, - List editors) - throws IOException { - this(forwardParams, fwdNode, destinationNode, false, null, editors); - } - - /** - * @param forwardParams optional advanced parameters (proxy, authentication, connection and TLS) - * @param fwdNode the DICOM forwarding node. Cannot be null. - * @param destinationNode the DICOM destination node. Cannot be null. - * @param useDestinationAetForKeyMap - * @param progress - * @param editors - * @throws IOException - */ - public DicomForwardDestination( - AdvancedParams forwardParams, - ForwardDicomNode fwdNode, - DicomNode destinationNode, - boolean useDestinationAetForKeyMap, - DicomProgress progress, - List editors) - throws IOException { - this( - null, - forwardParams, - fwdNode, - destinationNode, - useDestinationAetForKeyMap, - progress, - editors, - null, - true); - } - - public DicomForwardDestination( - Long id, - AdvancedParams forwardParams, - ForwardDicomNode fwdNode, - DicomNode destinationNode, - boolean useDestinationAetForKeyMap, - DicomProgress progress, - List editors, - String outputTransferSyntax, - boolean transcodeOnlyUncompressed) - throws IOException { - super(id, editors); - this.callingNode = fwdNode; - this.destinationNode = destinationNode; - this.streamSCU = new StoreFromStreamSCU(forwardParams, fwdNode, destinationNode, progress); - this.streamSCUService = new DeviceOpService(streamSCU.getDevice()); - this.useDestinationAetForKeyMap = useDestinationAetForKeyMap; - setOutputTransferSyntax(outputTransferSyntax); - setTranscodeOnlyUncompressed(transcodeOnlyUncompressed); - } - - public StoreFromStreamSCU getStreamSCU() { - return streamSCU; - } - - public DeviceOpService getStreamSCUService() { - return streamSCUService; - } - - public boolean isUseDestinationAetForKeyMap() { - return useDestinationAetForKeyMap; - } - - @Override - public ForwardDicomNode getForwardDicomNode() { - return callingNode; - } - - public DicomNode getDestinationNode() { - return destinationNode; - } - - @Override - public void stop() { - // Association as = streamSCU.getAssociation(); - // if (as != null && as.isReadyForDataTransfer()) { - // as.abort(); - // } - streamSCU.close(true); - streamSCUService.stop(); - } - - @Override - public DicomState getState() { - return streamSCU.getState(); - } - - @Override - public String toString() { - return destinationNode.toString(); - } + private final StoreFromStreamSCU streamSCU; + + private final DeviceOpService streamSCUService; + + private final boolean useDestinationAetForKeyMap; + + private final ForwardDicomNode callingNode; + + private final DicomNode destinationNode; + + public DicomForwardDestination(ForwardDicomNode fwdNode, DicomNode destinationNode) throws IOException { + this(null, fwdNode, destinationNode, null); + } + + public DicomForwardDestination(AdvancedParams forwardParams, ForwardDicomNode fwdNode, DicomNode destinationNode) + throws IOException { + this(forwardParams, fwdNode, destinationNode, null); + } + + public DicomForwardDestination(AdvancedParams forwardParams, ForwardDicomNode fwdNode, DicomNode destinationNode, + List editors) throws IOException { + this(forwardParams, fwdNode, destinationNode, false, null, editors); + } + + /** + * @param forwardParams optional advanced parameters (proxy, authentication, + * connection and TLS) + * @param fwdNode the DICOM forwarding node. Cannot be null. + * @param destinationNode the DICOM destination node. Cannot be null. + * @param useDestinationAetForKeyMap + * @param progress + * @param editors + * @throws IOException + */ + public DicomForwardDestination(AdvancedParams forwardParams, ForwardDicomNode fwdNode, DicomNode destinationNode, + boolean useDestinationAetForKeyMap, DicomProgress progress, List editors) + throws IOException { + this(null, forwardParams, fwdNode, destinationNode, useDestinationAetForKeyMap, progress, editors, null, true); + } + + public DicomForwardDestination(Long id, AdvancedParams forwardParams, ForwardDicomNode fwdNode, + DicomNode destinationNode, boolean useDestinationAetForKeyMap, DicomProgress progress, + List editors, String outputTransferSyntax, boolean transcodeOnlyUncompressed) + throws IOException { + super(id, editors); + this.callingNode = fwdNode; + this.destinationNode = destinationNode; + this.streamSCU = new StoreFromStreamSCU(forwardParams, fwdNode, destinationNode, progress); + this.streamSCUService = new DeviceOpService(streamSCU.getDevice()); + this.useDestinationAetForKeyMap = useDestinationAetForKeyMap; + setOutputTransferSyntax(outputTransferSyntax); + setTranscodeOnlyUncompressed(transcodeOnlyUncompressed); + } + + public StoreFromStreamSCU getStreamSCU() { + return streamSCU; + } + + public DeviceOpService getStreamSCUService() { + return streamSCUService; + } + + public boolean isUseDestinationAetForKeyMap() { + return useDestinationAetForKeyMap; + } + + @Override + public ForwardDicomNode getForwardDicomNode() { + return callingNode; + } + + public DicomNode getDestinationNode() { + return destinationNode; + } + + @Override + public void stop() { + // Association as = streamSCU.getAssociation(); + // if (as != null && as.isReadyForDataTransfer()) { + // as.abort(); + // } + streamSCU.close(true); + streamSCUService.stop(); + } + + @Override + public DicomState getState() { + return streamSCU.getState(); + } + + @Override + public String toString() { + return destinationNode.toString(); + } + } diff --git a/src/main/java/org/karnak/backend/dicom/ForwardDestination.java b/src/main/java/org/karnak/backend/dicom/ForwardDestination.java index 1c734419b..a1c1a4eaf 100644 --- a/src/main/java/org/karnak/backend/dicom/ForwardDestination.java +++ b/src/main/java/org/karnak/backend/dicom/ForwardDestination.java @@ -19,61 +19,63 @@ public abstract class ForwardDestination { - protected final List dicomEditors; - private final Long id; - private boolean transcodeOnlyUncompressed = true; - private String outputTransferSyntax = ""; - - protected ForwardDestination(Long id, List dicomEditors) { - this.dicomEditors = dicomEditors; - this.id = id; - } - - public List getDicomEditors() { - return dicomEditors; - } - - public Long getId() { - return id; - } - - public abstract ForwardDicomNode getForwardDicomNode(); - - public abstract void stop(); - - public abstract DicomState getState(); - - public String getOutputTransferSyntax() { - return outputTransferSyntax; - } - - public void setOutputTransferSyntax(String outputTransferSyntax) { - this.outputTransferSyntax = outputTransferSyntax != null ? outputTransferSyntax : ""; - } - - public boolean isTranscodeOnlyUncompressed() { - return transcodeOnlyUncompressed; - } - - public void setTranscodeOnlyUncompressed(boolean transcodeOnlyUncompressed) { - this.transcodeOnlyUncompressed = transcodeOnlyUncompressed; - } - - public String getOutputTransferSyntax(String originalTsuid) { - if (transcodeOnlyUncompressed - && !DicomUtils.isNative(originalTsuid) - && !UID.RLELossless.equals(originalTsuid)) { - return originalTsuid; - } - if (DicomOutputData.isSupportedSyntax(outputTransferSyntax) - && DicomImageReader.isSupportedSyntax(originalTsuid)) { - return outputTransferSyntax; - } - if (UID.RLELossless.equals(originalTsuid) - || UID.ImplicitVRLittleEndian.equals(originalTsuid) - || UID.ExplicitVRBigEndian.equals(originalTsuid)) { - return UID.ExplicitVRLittleEndian; - } - return originalTsuid; - } + protected final List dicomEditors; + + private final Long id; + + private boolean transcodeOnlyUncompressed = true; + + private String outputTransferSyntax = ""; + + protected ForwardDestination(Long id, List dicomEditors) { + this.dicomEditors = dicomEditors; + this.id = id; + } + + public List getDicomEditors() { + return dicomEditors; + } + + public Long getId() { + return id; + } + + public abstract ForwardDicomNode getForwardDicomNode(); + + public abstract void stop(); + + public abstract DicomState getState(); + + public String getOutputTransferSyntax() { + return outputTransferSyntax; + } + + public void setOutputTransferSyntax(String outputTransferSyntax) { + this.outputTransferSyntax = outputTransferSyntax != null ? outputTransferSyntax : ""; + } + + public boolean isTranscodeOnlyUncompressed() { + return transcodeOnlyUncompressed; + } + + public void setTranscodeOnlyUncompressed(boolean transcodeOnlyUncompressed) { + this.transcodeOnlyUncompressed = transcodeOnlyUncompressed; + } + + public String getOutputTransferSyntax(String originalTsuid) { + if (transcodeOnlyUncompressed && !DicomUtils.isNative(originalTsuid) + && !UID.RLELossless.equals(originalTsuid)) { + return originalTsuid; + } + if (DicomOutputData.isSupportedSyntax(outputTransferSyntax) + && DicomImageReader.isSupportedSyntax(originalTsuid)) { + return outputTransferSyntax; + } + if (UID.RLELossless.equals(originalTsuid) || UID.ImplicitVRLittleEndian.equals(originalTsuid) + || UID.ExplicitVRBigEndian.equals(originalTsuid)) { + return UID.ExplicitVRLittleEndian; + } + return originalTsuid; + } + } diff --git a/src/main/java/org/karnak/backend/dicom/ForwardDicomNode.java b/src/main/java/org/karnak/backend/dicom/ForwardDicomNode.java index 9845a21ff..84c2a2d51 100644 --- a/src/main/java/org/karnak/backend/dicom/ForwardDicomNode.java +++ b/src/main/java/org/karnak/backend/dicom/ForwardDicomNode.java @@ -15,75 +15,79 @@ public class ForwardDicomNode extends DicomNode { - private final String forwardAETitle; - private final Set acceptedSourceNodes; - private final Long id; - - public ForwardDicomNode(DicomNode dicomNode) { - this(dicomNode.getAet(), dicomNode.getHostname()); - } - - public ForwardDicomNode(String fwdAeTitle) { - this(fwdAeTitle, null); - } - - public ForwardDicomNode(String fwdAeTitle, String fwdHostname) { - this(fwdAeTitle, fwdHostname, null); - } - - public ForwardDicomNode(String fwdAeTitle, String fwdHostname, Long id) { - super(fwdAeTitle, fwdHostname, null); - this.forwardAETitle = fwdAeTitle; - this.id = id; - this.acceptedSourceNodes = new HashSet<>(); - } - - public void addAcceptedSourceNode(String srcAeTitle) { - addAcceptedSourceNode(srcAeTitle, null); - } - - public void addAcceptedSourceNode(String srcAeTitle, String srcHostname) { - acceptedSourceNodes.add( - new DicomNode(null, srcAeTitle, srcHostname, null, srcHostname != null)); - } - - public void addAcceptedSourceNode(Long id, String srcAeTitle, String srcHostname) { - acceptedSourceNodes.add(new DicomNode(id, srcAeTitle, srcHostname, null, srcHostname != null)); - } - - public Set getAcceptedSourceNodes() { - return acceptedSourceNodes; - } - - public String getForwardAETitle() { - return forwardAETitle; - } - - public Long getId() { - return id; - } - - @Override - public String toString() { - return forwardAETitle; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + forwardAETitle.hashCode(); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) return true; - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) return false; - ForwardDicomNode other = (ForwardDicomNode) obj; - return forwardAETitle.equals(other.forwardAETitle); - } + private final String forwardAETitle; + + private final Set acceptedSourceNodes; + + private final Long id; + + public ForwardDicomNode(DicomNode dicomNode) { + this(dicomNode.getAet(), dicomNode.getHostname()); + } + + public ForwardDicomNode(String fwdAeTitle) { + this(fwdAeTitle, null); + } + + public ForwardDicomNode(String fwdAeTitle, String fwdHostname) { + this(fwdAeTitle, fwdHostname, null); + } + + public ForwardDicomNode(String fwdAeTitle, String fwdHostname, Long id) { + super(fwdAeTitle, fwdHostname, null); + this.forwardAETitle = fwdAeTitle; + this.id = id; + this.acceptedSourceNodes = new HashSet<>(); + } + + public void addAcceptedSourceNode(String srcAeTitle) { + addAcceptedSourceNode(srcAeTitle, null); + } + + public void addAcceptedSourceNode(String srcAeTitle, String srcHostname) { + acceptedSourceNodes.add(new DicomNode(null, srcAeTitle, srcHostname, null, srcHostname != null)); + } + + public void addAcceptedSourceNode(Long id, String srcAeTitle, String srcHostname) { + acceptedSourceNodes.add(new DicomNode(id, srcAeTitle, srcHostname, null, srcHostname != null)); + } + + public Set getAcceptedSourceNodes() { + return acceptedSourceNodes; + } + + public String getForwardAETitle() { + return forwardAETitle; + } + + public Long getId() { + return id; + } + + @Override + public String toString() { + return forwardAETitle; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + forwardAETitle.hashCode(); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) + return false; + ForwardDicomNode other = (ForwardDicomNode) obj; + return forwardAETitle.equals(other.forwardAETitle); + } + } diff --git a/src/main/java/org/karnak/backend/dicom/GatewayParams.java b/src/main/java/org/karnak/backend/dicom/GatewayParams.java index 283d6cb83..c2b58c473 100644 --- a/src/main/java/org/karnak/backend/dicom/GatewayParams.java +++ b/src/main/java/org/karnak/backend/dicom/GatewayParams.java @@ -19,33 +19,26 @@ public class GatewayParams extends AbstractListenerParams { - public GatewayParams(boolean bindCallingAet) { - super(null, bindCallingAet, null); - } + public GatewayParams(boolean bindCallingAet) { + super(null, bindCallingAet, null); + } - public GatewayParams(AdvancedParams params, boolean bindCallingAet) { - super(params, bindCallingAet, null); - } + public GatewayParams(AdvancedParams params, boolean bindCallingAet) { + super(params, bindCallingAet, null); + } - public GatewayParams( - AdvancedParams params, - boolean bindCallingAet, - URL transferCapabilityFile, - String... acceptedCallingAETitles) { - super(params, bindCallingAet, transferCapabilityFile, acceptedCallingAETitles); - } + public GatewayParams(AdvancedParams params, boolean bindCallingAet, URL transferCapabilityFile, + String... acceptedCallingAETitles) { + super(params, bindCallingAet, transferCapabilityFile, acceptedCallingAETitles); + } + + public static String[] getAcceptedCallingAETitles(Map> destinations) { + Set set = destinations.keySet(); + if (set.stream().anyMatch(s -> s.getAcceptedSourceNodes().isEmpty())) { + return null; + } + return set.stream().map(ForwardDicomNode::getAcceptedSourceNodes).flatMap(Set::stream) + .map(DicomNode::getAet).distinct().toArray(String[]::new); + } - public static String[] getAcceptedCallingAETitles( - Map> destinations) { - Set set = destinations.keySet(); - if (set.stream().anyMatch(s -> s.getAcceptedSourceNodes().isEmpty())) { - return null; - } - return set.stream() - .map(ForwardDicomNode::getAcceptedSourceNodes) - .flatMap(Set::stream) - .map(DicomNode::getAet) - .distinct() - .toArray(String[]::new); - } } diff --git a/src/main/java/org/karnak/backend/dicom/ImageOrientation.java b/src/main/java/org/karnak/backend/dicom/ImageOrientation.java index aba17de45..0c0781687 100644 --- a/src/main/java/org/karnak/backend/dicom/ImageOrientation.java +++ b/src/main/java/org/karnak/backend/dicom/ImageOrientation.java @@ -10,247 +10,266 @@ package org.karnak.backend.dicom; /** - * A class of static methods to provide descriptions of images, including image orientation relative - * to the patient from the mathematical position and orientation attributes, and including other - * descriptive attributes such as from dicom directory records and images using multi-frame - * functional groups. + * A class of static methods to provide descriptions of images, including image + * orientation relative to the patient from the mathematical position and orientation + * attributes, and including other descriptive attributes such as from dicom directory + * records and images using multi-frame functional groups. * - *

C.7.6.1.1.1 Patient Orientation. The Patient Orientation (0020,0020) relative to the image - * plane shall be specified by two values that designate the anatomical direction of the positive - * row axis (left to right) and the positive column axis (top to bottom). The first entry is the - * direction of the rows, given by the direction of the last pixel in the first row from the first - * pixel in that row. The second entry is the direction of the columns, given by the direction of - * the last pixel in the first column from the first pixel in that column. Anatomical direction - * shall be designated by the capital letters: A (anterior), P (posterior), R (right), L (left), H - * (head), F (foot). Each value of the orientation attribute shall contain at least one of these - * characters. If refinements in the orientation descriptions are to be specified, then they shall - * be designated by one or two additional letters in each value. Within each value, the letters - * shall be ordered with the principal orientation designated in the first character. + *

+ * C.7.6.1.1.1 Patient Orientation. The Patient Orientation (0020,0020) relative to the + * image plane shall be specified by two values that designate the anatomical direction of + * the positive row axis (left to right) and the positive column axis (top to bottom). The + * first entry is the direction of the rows, given by the direction of the last pixel in + * the first row from the first pixel in that row. The second entry is the direction of + * the columns, given by the direction of the last pixel in the first column from the + * first pixel in that column. Anatomical direction shall be designated by the capital + * letters: A (anterior), P (posterior), R (right), L (left), H (head), F (foot). Each + * value of the orientation attribute shall contain at least one of these characters. If + * refinements in the orientation descriptions are to be specified, then they shall be + * designated by one or two additional letters in each value. Within each value, the + * letters shall be ordered with the principal orientation designated in the first + * character. * - *

C.7.6.2.1.1 Image Position And Image Orientation. The Image Position (0020,0032) specifies the - * x, y, and z coordinates of the upper left hand corner of the image; it is the center of the first - * voxel transmitted. Image Orientation (0020,0037) specifies the direction cosines of the first row - * and the first column with respect to the patient. These Attributes shall be provide as a pair. - * Row value for the x, y, and z axes respectively followed by the Column value for the x, y, and z - * axes respectively. The direction of the axes is defined fully by the patient's orientation. The - * x-axis is increasing to the left hand side of the patient. The y-axis is increasing to the - * posterior side of the patient. The z-axis is increasing toward the head of the patient. The - * patient based coordinate system is a right handed system, i.e. the vector cross product of a unit - * vector along the positive x-axis and a unit vector along the positive y-axis is equal to a unit - * vector along the positive z-axis. + *

+ * C.7.6.2.1.1 Image Position And Image Orientation. The Image Position (0020,0032) + * specifies the x, y, and z coordinates of the upper left hand corner of the image; it is + * the center of the first voxel transmitted. Image Orientation (0020,0037) specifies the + * direction cosines of the first row and the first column with respect to the patient. + * These Attributes shall be provide as a pair. Row value for the x, y, and z axes + * respectively followed by the Column value for the x, y, and z axes respectively. The + * direction of the axes is defined fully by the patient's orientation. The x-axis is + * increasing to the left hand side of the patient. The y-axis is increasing to the + * posterior side of the patient. The z-axis is increasing toward the head of the patient. + * The patient based coordinate system is a right handed system, i.e. the vector cross + * product of a unit vector along the positive x-axis and a unit vector along the positive + * y-axis is equal to a unit vector along the positive z-axis. * * @author David A. Clunie * @author Nicolas Roduit */ public abstract class ImageOrientation { - public enum Label { - UNKNOWN, - AXIAL, - SAGITTAL, - CORONAL, - OBLIQUE - } + public enum Label { - public static final String DIR_R = "R"; // NON-NLS - public static final String DIR_L = "L"; // NON-NLS - public static final String DIR_A = "A"; // NON-NLS - public static final String DIR_P = "P"; // NON-NLS - public static final String DIR_F = "F"; // NON-NLS - public static final String DIR_H = "H"; // NON-NLS + UNKNOWN, AXIAL, SAGITTAL, CORONAL, OBLIQUE - private static final double OBLIQUITY_THRESHOLD = 0.8; + } - /** - * Get a label describing the major axis from a unit vector (direction cosine) as found in - * ImageOrientationPatient. - * - *

Some degree of deviation from one of the standard orthogonal axes is allowed before deciding - * no major axis applies and returning null. - * - * @param x - * @param y - * @param z - * @return the string describing the orientation of the vector, or null if oblique - */ - public static final String getMajorAxisFromPatientRelativeDirectionCosine( - double x, double y, double z) { - String axis = null; + public static final String DIR_R = "R"; // NON-NLS - String orientationX = x < 0 ? DIR_R : DIR_L; - String orientationY = y < 0 ? DIR_A : DIR_P; - String orientationZ = z < 0 ? DIR_F : DIR_H; + public static final String DIR_L = "L"; // NON-NLS - double absX = Math.abs(x); - double absY = Math.abs(y); - double absZ = Math.abs(z); + public static final String DIR_A = "A"; // NON-NLS - // The tests here really don't need to check the other dimensions, - // just the threshold, since the sum of the squares should be == 1.0 - // but just in case ... + public static final String DIR_P = "P"; // NON-NLS - if (absX > OBLIQUITY_THRESHOLD && absX > absY && absX > absZ) { - axis = orientationX; - } else if (absY > OBLIQUITY_THRESHOLD && absY > absX && absY > absZ) { - axis = orientationY; - } else if (absZ > OBLIQUITY_THRESHOLD && absZ > absX && absZ > absY) { - axis = orientationZ; - } + public static final String DIR_F = "F"; // NON-NLS - return axis; - } + public static final String DIR_H = "H"; // NON-NLS - /** - * Get a label describing the axial, coronal or sagittal plane from row and column unit vectors - * (direction cosines) as found in ImageOrientationPatient. - * - *

Some degree of deviation from one of the standard orthogonal planes is allowed before - * deciding the plane is OBLIQUE. - * - * @param rowX - * @param rowY - * @param rowZ - * @param colX - * @param colY - * @param colZ - * @return the string describing the plane of orientation, AXIAL, CORONAL, SAGITTAL or OBLIQUE - */ - public static final Label makeImageOrientationLabelFromImageOrientationPatient( - double rowX, double rowY, double rowZ, double colX, double colY, double colZ) { - String rowAxis = getMajorAxisFromPatientRelativeDirectionCosine(rowX, rowY, rowZ); - String colAxis = getMajorAxisFromPatientRelativeDirectionCosine(colX, colY, colZ); - if (rowAxis != null && colAxis != null) { - if ((rowAxis.equals(DIR_R) || rowAxis.equals(DIR_L)) - && (colAxis.equals(DIR_A) || colAxis.equals(DIR_P))) { - return Label.AXIAL; - } else if ((colAxis.equals(DIR_R) || colAxis.equals(DIR_L)) - && (rowAxis.equals(DIR_A) || rowAxis.equals(DIR_P))) { - return Label.AXIAL; - } else if ((rowAxis.equals(DIR_R) || rowAxis.equals(DIR_L)) - && (colAxis.equals(DIR_H) || colAxis.equals(DIR_F))) { - return Label.CORONAL; - } else if ((colAxis.equals(DIR_R) || colAxis.equals(DIR_L)) - && (rowAxis.equals(DIR_H) || rowAxis.equals(DIR_F))) { - return Label.CORONAL; - } else if ((rowAxis.equals(DIR_A) || rowAxis.equals(DIR_P)) - && (colAxis.equals(DIR_H) || colAxis.equals(DIR_F))) { - return Label.SAGITTAL; - } else if ((colAxis.equals(DIR_A) || colAxis.equals(DIR_P)) - && (rowAxis.equals(DIR_H) || rowAxis.equals(DIR_F))) { - return Label.SAGITTAL; - } - } - return Label.OBLIQUE; - } + private static final double OBLIQUITY_THRESHOLD = 0.8; - public static final Label makeImageOrientationLabelFromImageOrientationPatient(double[] v) { - if (v == null || v.length < 6) { - return null; - } - return ImageOrientation.makeImageOrientationLabelFromImageOrientationPatient( - v[0], v[1], v[2], v[3], v[4], v[5]); - } + /** + * Get a label describing the major axis from a unit vector (direction cosine) as + * found in ImageOrientationPatient. + * + *

+ * Some degree of deviation from one of the standard orthogonal axes is allowed before + * deciding no major axis applies and returning null. + * @param x + * @param y + * @param z + * @return the string describing the orientation of the vector, or null if oblique + */ + public static final String getMajorAxisFromPatientRelativeDirectionCosine(double x, double y, double z) { + String axis = null; - /** - * Get a PatientOrientation style string from a unit vector (direction cosine) as found in - * ImageOrientationPatient. - * - *

Returns letters representing R (right) or L (left), A (anterior) or P (posterior), F (feet) - * or H (head). - * - *

If the orientation is not precisely orthogonal to one of the major axes, more than one - * letter is returned, from major to minor axes, with up to three letters in the case of a "double - * oblique". - * - * @param x - * @param y - * @param z - * @return the string describing the orientation of the vector - */ - public static final String makePatientOrientationFromPatientRelativeDirectionCosine( - double x, double y, double z) { - StringBuilder buffer = new StringBuilder(); + String orientationX = x < 0 ? DIR_R : DIR_L; + String orientationY = y < 0 ? DIR_A : DIR_P; + String orientationZ = z < 0 ? DIR_F : DIR_H; - String orientationX = x < 0 ? DIR_R : DIR_L; - String orientationY = y < 0 ? DIR_A : DIR_P; - String orientationZ = z < 0 ? DIR_F : DIR_H; + double absX = Math.abs(x); + double absY = Math.abs(y); + double absZ = Math.abs(z); - double absX = Math.abs(x); - double absY = Math.abs(y); - double absZ = Math.abs(z); + // The tests here really don't need to check the other dimensions, + // just the threshold, since the sum of the squares should be == 1.0 + // but just in case ... - for (int i = 0; i < 3; ++i) { - if (absX > .0001 && absX >= absY && absX >= absZ) { - buffer.append(orientationX); - absX = 0; - } else if (absY > .0001 && absY >= absX && absY >= absZ) { - buffer.append(orientationY); - absY = 0; - } else if (absZ > .0001 && absZ >= absX && absZ >= absY) { - buffer.append(orientationZ); - absZ = 0; - } else { - break; - } - } - return buffer.toString(); - } + if (absX > OBLIQUITY_THRESHOLD && absX > absY && absX > absZ) { + axis = orientationX; + } + else if (absY > OBLIQUITY_THRESHOLD && absY > absX && absY > absZ) { + axis = orientationY; + } + else if (absZ > OBLIQUITY_THRESHOLD && absZ > absX && absZ > absY) { + axis = orientationZ; + } - /** - * Get a PatientOrientation style string from row and column unit vectors (direction cosines) as - * found in ImageOrientationPatient. - * - *

Returns letters representing R (right) or L (left), A (anterior) or P (posterior), F (feet) - * or H (head). - * - *

If the orientation is not precisely orthogonal to one of the major axes, more than one - * letter is returned, from major to minor axes, with up to three letters in the case of a "double - * oblique". - * - *

The row and column letters returned are separated by the usual DICOM string delimiter, a - * backslash. - * - * @param rowX - * @param rowY - * @param rowZ - * @param colX - * @param colY - * @param colZ - * @return the string describing the row and then the column - */ - public static final String makePatientOrientationFromImageOrientationPatient( - double rowX, double rowY, double rowZ, double colX, double colY, double colZ) { - return makePatientOrientationFromPatientRelativeDirectionCosine(rowX, rowY, rowZ) - + "\\" - + makePatientOrientationFromPatientRelativeDirectionCosine(colX, colY, colZ); - } + return axis; + } - public static final char getImageOrientationOposite(char c) { - switch (c) { - case 'L': - return 'R'; - case 'R': - return 'L'; - case 'P': - return 'A'; - case 'A': - return 'P'; - case 'H': - return 'F'; - case 'F': - return 'H'; - } - return ' '; - } + /** + * Get a label describing the axial, coronal or sagittal plane from row and column + * unit vectors (direction cosines) as found in ImageOrientationPatient. + * + *

+ * Some degree of deviation from one of the standard orthogonal planes is allowed + * before deciding the plane is OBLIQUE. + * @param rowX + * @param rowY + * @param rowZ + * @param colX + * @param colY + * @param colZ + * @return the string describing the plane of orientation, AXIAL, CORONAL, SAGITTAL or + * OBLIQUE + */ + public static final Label makeImageOrientationLabelFromImageOrientationPatient(double rowX, double rowY, + double rowZ, double colX, double colY, double colZ) { + String rowAxis = getMajorAxisFromPatientRelativeDirectionCosine(rowX, rowY, rowZ); + String colAxis = getMajorAxisFromPatientRelativeDirectionCosine(colX, colY, colZ); + if (rowAxis != null && colAxis != null) { + if ((rowAxis.equals(DIR_R) || rowAxis.equals(DIR_L)) && (colAxis.equals(DIR_A) || colAxis.equals(DIR_P))) { + return Label.AXIAL; + } + else if ((colAxis.equals(DIR_R) || colAxis.equals(DIR_L)) + && (rowAxis.equals(DIR_A) || rowAxis.equals(DIR_P))) { + return Label.AXIAL; + } + else if ((rowAxis.equals(DIR_R) || rowAxis.equals(DIR_L)) + && (colAxis.equals(DIR_H) || colAxis.equals(DIR_F))) { + return Label.CORONAL; + } + else if ((colAxis.equals(DIR_R) || colAxis.equals(DIR_L)) + && (rowAxis.equals(DIR_H) || rowAxis.equals(DIR_F))) { + return Label.CORONAL; + } + else if ((rowAxis.equals(DIR_A) || rowAxis.equals(DIR_P)) + && (colAxis.equals(DIR_H) || colAxis.equals(DIR_F))) { + return Label.SAGITTAL; + } + else if ((colAxis.equals(DIR_A) || colAxis.equals(DIR_P)) + && (rowAxis.equals(DIR_H) || rowAxis.equals(DIR_F))) { + return Label.SAGITTAL; + } + } + return Label.OBLIQUE; + } + + public static final Label makeImageOrientationLabelFromImageOrientationPatient(double[] v) { + if (v == null || v.length < 6) { + return null; + } + return ImageOrientation.makeImageOrientationLabelFromImageOrientationPatient(v[0], v[1], v[2], v[3], v[4], + v[5]); + } + + /** + * Get a PatientOrientation style string from a unit vector (direction cosine) as + * found in ImageOrientationPatient. + * + *

+ * Returns letters representing R (right) or L (left), A (anterior) or P (posterior), + * F (feet) or H (head). + * + *

+ * If the orientation is not precisely orthogonal to one of the major axes, more than + * one letter is returned, from major to minor axes, with up to three letters in the + * case of a "double oblique". + * @param x + * @param y + * @param z + * @return the string describing the orientation of the vector + */ + public static final String makePatientOrientationFromPatientRelativeDirectionCosine(double x, double y, double z) { + StringBuilder buffer = new StringBuilder(); + + String orientationX = x < 0 ? DIR_R : DIR_L; + String orientationY = y < 0 ? DIR_A : DIR_P; + String orientationZ = z < 0 ? DIR_F : DIR_H; + + double absX = Math.abs(x); + double absY = Math.abs(y); + double absZ = Math.abs(z); + + for (int i = 0; i < 3; ++i) { + if (absX > .0001 && absX >= absY && absX >= absZ) { + buffer.append(orientationX); + absX = 0; + } + else if (absY > .0001 && absY >= absX && absY >= absZ) { + buffer.append(orientationY); + absY = 0; + } + else if (absZ > .0001 && absZ >= absX && absZ >= absY) { + buffer.append(orientationZ); + absZ = 0; + } + else { + break; + } + } + return buffer.toString(); + } + + /** + * Get a PatientOrientation style string from row and column unit vectors (direction + * cosines) as found in ImageOrientationPatient. + * + *

+ * Returns letters representing R (right) or L (left), A (anterior) or P (posterior), + * F (feet) or H (head). + * + *

+ * If the orientation is not precisely orthogonal to one of the major axes, more than + * one letter is returned, from major to minor axes, with up to three letters in the + * case of a "double oblique". + * + *

+ * The row and column letters returned are separated by the usual DICOM string + * delimiter, a backslash. + * @param rowX + * @param rowY + * @param rowZ + * @param colX + * @param colY + * @param colZ + * @return the string describing the row and then the column + */ + public static final String makePatientOrientationFromImageOrientationPatient(double rowX, double rowY, double rowZ, + double colX, double colY, double colZ) { + return makePatientOrientationFromPatientRelativeDirectionCosine(rowX, rowY, rowZ) + "\\" + + makePatientOrientationFromPatientRelativeDirectionCosine(colX, colY, colZ); + } + + public static final char getImageOrientationOposite(char c) { + switch (c) { + case 'L': + return 'R'; + case 'R': + return 'L'; + case 'P': + return 'A'; + case 'A': + return 'P'; + case 'H': + return 'F'; + case 'F': + return 'H'; + } + return ' '; + } + + public static double[] computeNormalVectorOfPlan(double[] vector) { + if (vector != null && vector.length == 6) { + double[] norm = new double[3]; + norm[0] = vector[1] * vector[5] - vector[2] * vector[4]; + norm[1] = vector[2] * vector[3] - vector[0] * vector[5]; + norm[2] = vector[0] * vector[4] - vector[1] * vector[3]; + return norm; + } + return null; + } - public static double[] computeNormalVectorOfPlan(double[] vector) { - if (vector != null && vector.length == 6) { - double[] norm = new double[3]; - norm[0] = vector[1] * vector[5] - vector[2] * vector[4]; - norm[1] = vector[2] * vector[3] - vector[0] * vector[5]; - norm[2] = vector[0] * vector[4] - vector[1] * vector[3]; - return norm; - } - return null; - } } diff --git a/src/main/java/org/karnak/backend/dicom/Params.java b/src/main/java/org/karnak/backend/dicom/Params.java index 460c40480..7b454d307 100644 --- a/src/main/java/org/karnak/backend/dicom/Params.java +++ b/src/main/java/org/karnak/backend/dicom/Params.java @@ -14,45 +14,50 @@ public final class Params { - private final String iuid; - private final String cuid; - private final String tsuid; - private final InputStream data; - private final Association as; - private final int priority; - - public Params( - String iuid, String cuid, String tsuid, int priority, InputStream data, Association as) { - super(); - this.iuid = iuid; - this.cuid = cuid; - this.tsuid = tsuid; - this.priority = priority; - this.as = as; - this.data = data; - } - - public String getIuid() { - return iuid; - } - - public String getCuid() { - return cuid; - } - - public String getTsuid() { - return tsuid; - } - - public int getPriority() { - return priority; - } - - public Association getAs() { - return as; - } - - public InputStream getData() { - return data; - } + private final String iuid; + + private final String cuid; + + private final String tsuid; + + private final InputStream data; + + private final Association as; + + private final int priority; + + public Params(String iuid, String cuid, String tsuid, int priority, InputStream data, Association as) { + super(); + this.iuid = iuid; + this.cuid = cuid; + this.tsuid = tsuid; + this.priority = priority; + this.as = as; + this.data = data; + } + + public String getIuid() { + return iuid; + } + + public String getCuid() { + return cuid; + } + + public String getTsuid() { + return tsuid; + } + + public int getPriority() { + return priority; + } + + public Association getAs() { + return as; + } + + public InputStream getData() { + return data; + } + } diff --git a/src/main/java/org/karnak/backend/dicom/WebForwardDestination.java b/src/main/java/org/karnak/backend/dicom/WebForwardDestination.java index 26c24e4f1..5fd282e00 100644 --- a/src/main/java/org/karnak/backend/dicom/WebForwardDestination.java +++ b/src/main/java/org/karnak/backend/dicom/WebForwardDestination.java @@ -21,97 +21,79 @@ public class WebForwardDestination extends ForwardDestination { - private final ForwardDicomNode callingNode; - private final DicomState state; - private final DicomStowRS stowRS; - - public WebForwardDestination(ForwardDicomNode fwdNode, String requestURL) { - this(fwdNode, requestURL, null); - } - - public WebForwardDestination( - ForwardDicomNode fwdNode, String requestURL, List editors) { - this(fwdNode, requestURL, null, editors); - } - - public WebForwardDestination( - ForwardDicomNode fwdNode, - String requestURL, - DicomProgress progress, - List editors) { - this(fwdNode, requestURL, null, progress, editors); - } - - public WebForwardDestination( - ForwardDicomNode fwdNode, - String requestURL, - Map headers, - DicomProgress progress, - List editors) { - this(null, fwdNode, requestURL, headers, progress, editors, null, true); - } - - public WebForwardDestination( - Long id, - ForwardDicomNode fwdNode, - String requestURL, - Map headers, - DicomProgress progress, - List editors, - String outputTransferSyntax, - boolean transcodeOnlyUncompressed) { - super(id, editors); - this.callingNode = fwdNode; - this.state = new DicomState(progress == null ? new DicomProgress() : progress); - this.stowRS = new DicomStowRS(requestURL, ContentType.APPLICATION_DICOM, null, headers); - setOutputTransferSyntax(outputTransferSyntax); - setTranscodeOnlyUncompressed(transcodeOnlyUncompressed); - } - - public WebForwardDestination( - ForwardDicomNode fwdNode, - DicomStowRS uploadManager, - DicomProgress progress, - List editors) { - this(null, fwdNode, uploadManager, progress, editors); - } - - public WebForwardDestination( - Long id, - ForwardDicomNode fwdNode, - DicomStowRS uploadManager, - DicomProgress progress, - List editors) { - super(id, editors); - this.callingNode = fwdNode; - this.state = new DicomState(progress == null ? new DicomProgress() : progress); - this.stowRS = uploadManager; - } - - @Override - public ForwardDicomNode getForwardDicomNode() { - return callingNode; - } - - public String getRequestURL() { - return stowRS.getRequestURL(); - } - - public DicomStowRS getStowrsSingleFile() throws IOException { - return stowRS; - } - - @Override - public void stop() { - FileUtil.safeClose(stowRS); - } - - @Override - public String toString() { - return stowRS.getRequestURL(); - } - - public DicomState getState() { - return state; - } + private final ForwardDicomNode callingNode; + + private final DicomState state; + + private final DicomStowRS stowRS; + + public WebForwardDestination(ForwardDicomNode fwdNode, String requestURL) { + this(fwdNode, requestURL, null); + } + + public WebForwardDestination(ForwardDicomNode fwdNode, String requestURL, List editors) { + this(fwdNode, requestURL, null, editors); + } + + public WebForwardDestination(ForwardDicomNode fwdNode, String requestURL, DicomProgress progress, + List editors) { + this(fwdNode, requestURL, null, progress, editors); + } + + public WebForwardDestination(ForwardDicomNode fwdNode, String requestURL, Map headers, + DicomProgress progress, List editors) { + this(null, fwdNode, requestURL, headers, progress, editors, null, true); + } + + public WebForwardDestination(Long id, ForwardDicomNode fwdNode, String requestURL, Map headers, + DicomProgress progress, List editors, String outputTransferSyntax, + boolean transcodeOnlyUncompressed) { + super(id, editors); + this.callingNode = fwdNode; + this.state = new DicomState(progress == null ? new DicomProgress() : progress); + this.stowRS = new DicomStowRS(requestURL, ContentType.APPLICATION_DICOM, null, headers); + setOutputTransferSyntax(outputTransferSyntax); + setTranscodeOnlyUncompressed(transcodeOnlyUncompressed); + } + + public WebForwardDestination(ForwardDicomNode fwdNode, DicomStowRS uploadManager, DicomProgress progress, + List editors) { + this(null, fwdNode, uploadManager, progress, editors); + } + + public WebForwardDestination(Long id, ForwardDicomNode fwdNode, DicomStowRS uploadManager, DicomProgress progress, + List editors) { + super(id, editors); + this.callingNode = fwdNode; + this.state = new DicomState(progress == null ? new DicomProgress() : progress); + this.stowRS = uploadManager; + } + + @Override + public ForwardDicomNode getForwardDicomNode() { + return callingNode; + } + + public String getRequestURL() { + return stowRS.getRequestURL(); + } + + public DicomStowRS getStowrsSingleFile() throws IOException { + return stowRS; + } + + @Override + public void stop() { + FileUtil.safeClose(stowRS); + } + + @Override + public String toString() { + return stowRS.getRequestURL(); + } + + public DicomState getState() { + return state; + } + } diff --git a/src/main/java/org/karnak/backend/enums/ApplicationProfile.java b/src/main/java/org/karnak/backend/enums/ApplicationProfile.java index 020f61294..aaea577b4 100644 --- a/src/main/java/org/karnak/backend/enums/ApplicationProfile.java +++ b/src/main/java/org/karnak/backend/enums/ApplicationProfile.java @@ -12,17 +12,18 @@ /** Application profile */ public enum ApplicationProfile { - /** Profile OIDC: use to activate the application profile: application-oidc.yml */ - OIDC("oidc"); + /** Profile OIDC: use to activate the application profile: application-oidc.yml */ + OIDC("oidc"); - /** Name of the profile to activate */ - final String code; + /** Name of the profile to activate */ + final String code; - ApplicationProfile(final String code) { - this.code = code; - } + ApplicationProfile(final String code) { + this.code = code; + } + + public String getCode() { + return code; + } - public String getCode() { - return code; - } } diff --git a/src/main/java/org/karnak/backend/enums/DestinationType.java b/src/main/java/org/karnak/backend/enums/DestinationType.java index 3a18527ef..a8ca05fbc 100644 --- a/src/main/java/org/karnak/backend/enums/DestinationType.java +++ b/src/main/java/org/karnak/backend/enums/DestinationType.java @@ -10,6 +10,7 @@ package org.karnak.backend.enums; public enum DestinationType { - dicom, - stow + + dicom, stow + } diff --git a/src/main/java/org/karnak/backend/enums/EnvironmentVariable.java b/src/main/java/org/karnak/backend/enums/EnvironmentVariable.java index 0e62e4036..245143dab 100644 --- a/src/main/java/org/karnak/backend/enums/EnvironmentVariable.java +++ b/src/main/java/org/karnak/backend/enums/EnvironmentVariable.java @@ -12,20 +12,21 @@ /** Environment variables of the system */ public enum EnvironmentVariable { - /** - * Environment variable IDP: determine the identity provider to use: "oidc": load keycloak, any - * other: load in memory - */ - IDP("IDP"); + /** + * Environment variable IDP: determine the identity provider to use: "oidc": load + * keycloak, any other: load in memory + */ + IDP("IDP"); - /** Name of the environment variable */ - final String code; + /** Name of the environment variable */ + final String code; - EnvironmentVariable(final String code) { - this.code = code; - } + EnvironmentVariable(final String code) { + this.code = code; + } + + public String getCode() { + return code; + } - public String getCode() { - return code; - } } diff --git a/src/main/java/org/karnak/backend/enums/MessageFormat.java b/src/main/java/org/karnak/backend/enums/MessageFormat.java index 7576ec51d..1c1bba1b2 100644 --- a/src/main/java/org/karnak/backend/enums/MessageFormat.java +++ b/src/main/java/org/karnak/backend/enums/MessageFormat.java @@ -10,6 +10,7 @@ package org.karnak.backend.enums; public enum MessageFormat { - TEXT, - HTML + + TEXT, HTML + } diff --git a/src/main/java/org/karnak/backend/enums/MessageLevel.java b/src/main/java/org/karnak/backend/enums/MessageLevel.java index f4478fcf6..d1f4715ae 100644 --- a/src/main/java/org/karnak/backend/enums/MessageLevel.java +++ b/src/main/java/org/karnak/backend/enums/MessageLevel.java @@ -10,7 +10,7 @@ package org.karnak.backend.enums; public enum MessageLevel { - INFO, - WARN, - ERROR + + INFO, WARN, ERROR + } diff --git a/src/main/java/org/karnak/backend/enums/MessageType.java b/src/main/java/org/karnak/backend/enums/MessageType.java index 4196b78c0..aa2dfa132 100644 --- a/src/main/java/org/karnak/backend/enums/MessageType.java +++ b/src/main/java/org/karnak/backend/enums/MessageType.java @@ -10,6 +10,9 @@ package org.karnak.backend.enums; public enum MessageType { - NOTIFICATION_MESSAGE, // The message is displayed in a Notification - STATIC_MESSAGE // The message is displayed inside the current component (Dialog, Layout, ...) + + NOTIFICATION_MESSAGE, // The message is displayed in a Notification + STATIC_MESSAGE // The message is displayed inside the current component (Dialog, + // Layout, ...) + } diff --git a/src/main/java/org/karnak/backend/enums/Modality.java b/src/main/java/org/karnak/backend/enums/Modality.java index 0aeb12e0c..aec7cd7df 100644 --- a/src/main/java/org/karnak/backend/enums/Modality.java +++ b/src/main/java/org/karnak/backend/enums/Modality.java @@ -10,118 +10,121 @@ package org.karnak.backend.enums; public enum Modality { - ALL("No filter"), - AU("Audio"), // $NON-NLS-1$ + ALL("No filter"), - BI("Biomagnetic imaging"), // $NON-NLS-1$ + AU("Audio"), // $NON-NLS-1$ - CD("Color flow Doppler"), // $NON-NLS-1$ + BI("Biomagnetic imaging"), // $NON-NLS-1$ - DD("Duplex Doppler"), // $NON-NLS-1$ + CD("Color flow Doppler"), // $NON-NLS-1$ - DG("Diaphanography"), // $NON-NLS-1$ + DD("Duplex Doppler"), // $NON-NLS-1$ - CR("Computed Radiography"), // $NON-NLS-1$ + DG("Diaphanography"), // $NON-NLS-1$ - CT("Computed Tomography"), // $NON-NLS-1$ + CR("Computed Radiography"), // $NON-NLS-1$ - DX("Digital Radiography"), // $NON-NLS-1$ + CT("Computed Tomography"), // $NON-NLS-1$ - ECG("Electrocardiography"), // $NON-NLS-1$ + DX("Digital Radiography"), // $NON-NLS-1$ - EPS("Cardiac Electrophysiology"), // $NON-NLS-1$ + ECG("Electrocardiography"), // $NON-NLS-1$ - ES("Endoscopy"), // $NON-NLS-1$ + EPS("Cardiac Electrophysiology"), // $NON-NLS-1$ - GM("General Microscopy"), // $NON-NLS-1$ + ES("Endoscopy"), // $NON-NLS-1$ - HC("Hard Copy"), // $NON-NLS-1$ + GM("General Microscopy"), // $NON-NLS-1$ - HD("Hemodynamic Waveform"), // $NON-NLS-1$ + HC("Hard Copy"), // $NON-NLS-1$ - IO("Intra-oral Radiography"), // $NON-NLS-1$ + HD("Hemodynamic Waveform"), // $NON-NLS-1$ - IVUS("Intravascular Ultrasound"), // $NON-NLS-1$ + IO("Intra-oral Radiography"), // $NON-NLS-1$ - LS("Laser surface scan"), // $NON-NLS-1$ + IVUS("Intravascular Ultrasound"), // $NON-NLS-1$ - MG("Mammography"), // $NON-NLS-1$ + LS("Laser surface scan"), // $NON-NLS-1$ - MR("Magnetic Resonance"), // $NON-NLS-1$ + MG("Mammography"), // $NON-NLS-1$ - NM("Nuclear Medicine"), // $NON-NLS-1$ + MR("Magnetic Resonance"), // $NON-NLS-1$ - OT("Other"), // $NON-NLS-1$ + NM("Nuclear Medicine"), // $NON-NLS-1$ - OP("Ophthalmic Photography"), // $NON-NLS-1$ + OT("Other"), // $NON-NLS-1$ - PR("Presentation State"), // $NON-NLS-1$ + OP("Ophthalmic Photography"), // $NON-NLS-1$ - PX("Panoramic X-Ray"), // $NON-NLS-1$ + PR("Presentation State"), // $NON-NLS-1$ - PT("Positron emission tomography (PET)"), // $NON-NLS-1$ + PX("Panoramic X-Ray"), // $NON-NLS-1$ - RF("Radio Fluoroscopy"), // $NON-NLS-1$ + PT("Positron emission tomography (PET)"), // $NON-NLS-1$ - RG("Radiographic imaging (conventional film/screen)"), // $NON-NLS-1$ + RF("Radio Fluoroscopy"), // $NON-NLS-1$ - RTDOSE("Radiotherapy Dose"), // $NON-NLS-1$ + RG("Radiographic imaging (conventional film/screen)"), // $NON-NLS-1$ - RTIMAGE("Radiotherapy Image"), // $NON-NLS-1$ + RTDOSE("Radiotherapy Dose"), // $NON-NLS-1$ - RTPLAN("Radiotherapy Plan"), // $NON-NLS-1$ + RTIMAGE("Radiotherapy Image"), // $NON-NLS-1$ - RTRECORD("RT Treatment Record"), // $NON-NLS-1$ + RTPLAN("Radiotherapy Plan"), // $NON-NLS-1$ - RTSTRUCT("Radiotherapy Structure Set"), // $NON-NLS-1$ + RTRECORD("RT Treatment Record"), // $NON-NLS-1$ - SC("Secondary Capture"), // $NON-NLS-1$ + RTSTRUCT("Radiotherapy Structure Set"), // $NON-NLS-1$ - SM("Slide Microscopy"), // $NON-NLS-1$ + SC("Secondary Capture"), // $NON-NLS-1$ - SMR("Stereometric Relationship"), // $NON-NLS-1$ + SM("Slide Microscopy"), // $NON-NLS-1$ - SR("SR Document"), // $NON-NLS-1$ + SMR("Stereometric Relationship"), // $NON-NLS-1$ - ST("Single-photon emission computed tomography (SPECT)"), // $NON-NLS-1$ + SR("SR Document"), // $NON-NLS-1$ - TG("Thermography"), // $NON-NLS-1$ + ST("Single-photon emission computed tomography (SPECT)"), // $NON-NLS-1$ - US("Ultrasound"), // $NON-NLS-1$ + TG("Thermography"), // $NON-NLS-1$ - XA("X-Ray Angiography"), // $NON-NLS-1$ + US("Ultrasound"), // $NON-NLS-1$ - XC("External-camera Photography"); // $NON-NLS-1$ + XA("X-Ray Angiography"), // $NON-NLS-1$ - private final String description; + XC("External-camera Photography"); // $NON-NLS-1$ - Modality(String description) { - this.description = description; - } + private final String description; - public static Modality getModality(String modality) { - Modality v = Modality.ALL; - if (modality != null) { - try { - v = Modality.valueOf(modality); - } catch (Exception e) { - // System.err.println("Modality not supported: " + modality); - } - } - return v; - } + Modality(String description) { + this.description = description; + } - public String getDescription() { - return description; - } + public static Modality getModality(String modality) { + Modality v = Modality.ALL; + if (modality != null) { + try { + v = Modality.valueOf(modality); + } + catch (Exception e) { + // System.err.println("Modality not supported: " + modality); + } + } + return v; + } + + public String getDescription() { + return description; + } + + @Override + public String toString() { + StringBuilder buf = new StringBuilder(name()); + buf.append(" ("); + buf.append(description); + buf.append(")"); + return buf.toString(); + } - @Override - public String toString() { - StringBuilder buf = new StringBuilder(name()); - buf.append(" ("); - buf.append(description); - buf.append(")"); - return buf.toString(); - } } diff --git a/src/main/java/org/karnak/backend/enums/NodeEventType.java b/src/main/java/org/karnak/backend/enums/NodeEventType.java index 4e0586209..ee7d484e9 100644 --- a/src/main/java/org/karnak/backend/enums/NodeEventType.java +++ b/src/main/java/org/karnak/backend/enums/NodeEventType.java @@ -10,7 +10,7 @@ package org.karnak.backend.enums; public enum NodeEventType { - ADD, - UPDATE, - REMOVE + + ADD, UPDATE, REMOVE + } diff --git a/src/main/java/org/karnak/backend/enums/ProfileItemType.java b/src/main/java/org/karnak/backend/enums/ProfileItemType.java index c3bb12152..d0e9c77c4 100644 --- a/src/main/java/org/karnak/backend/enums/ProfileItemType.java +++ b/src/main/java/org/karnak/backend/enums/ProfileItemType.java @@ -20,76 +20,66 @@ import org.karnak.backend.model.profiles.UpdateUIDsProfile; public enum ProfileItemType { - BASIC_DICOM( - BasicProfile.class, - "basic.dicom.profile", - "113100", - "Basic Application Confidentiality Profile"), - CLEAN_PIXEL_DATA(CleanPixelData.class, "clean.pixel.data", "113101", "Clean Pixel Data Option"), - DEFACING( - Defacing.class, - "clean.recognizable.visual.features", - "113102", - "Clean Recognizable Visual Features Option"), - REPLACE_UID(UpdateUIDsProfile.class, "replace.uid", null, null), - ACTION_TAGS(ActionTags.class, "action.on.specific.tags", null, null), - ACTION_PRIVATETAGS( - PrivateTags.class, "action.on.privatetags", "113111", "Retain Safe Private Option"), - ACTION_DATES( - ActionDates.class, - "action.on.dates", - "113107", - "Retain Longitudinal Temporal Information Modified Dates Option"), - EXPRESSION_TAGS(Expression.class, "expression.on.tags", null, null); - private final Class profileClass; - private final String classAlias; - private final String codeValue; - private final String codeMeaning; + BASIC_DICOM(BasicProfile.class, "basic.dicom.profile", "113100", + "Basic Application Confidentiality Profile"), CLEAN_PIXEL_DATA(CleanPixelData.class, "clean.pixel.data", + "113101", "Clean Pixel Data Option"), DEFACING(Defacing.class, "clean.recognizable.visual.features", + "113102", "Clean Recognizable Visual Features Option"), REPLACE_UID(UpdateUIDsProfile.class, + "replace.uid", null, null), ACTION_TAGS(ActionTags.class, "action.on.specific.tags", + null, null), ACTION_PRIVATETAGS(PrivateTags.class, "action.on.privatetags", + "113111", "Retain Safe Private Option"), ACTION_DATES( + ActionDates.class, "action.on.dates", "113107", + "Retain Longitudinal Temporal Information Modified Dates Option"), EXPRESSION_TAGS( + Expression.class, "expression.on.tags", null, null); - ProfileItemType( - Class profileClass, - String alias, - String codeValue, - String codeMeaning) { - this.profileClass = profileClass; - this.classAlias = alias; - this.codeValue = codeValue; - this.codeMeaning = codeMeaning; - } + private final Class profileClass; - public static ProfileItemType getType(String alias) { - for (ProfileItemType t : ProfileItemType.values()) { - if (t.classAlias.equals(alias)) { - return t; - } - } - return null; - } + private final String classAlias; - public static String getCodeValue(String alias) { - for (ProfileItemType t : ProfileItemType.values()) { - if (t.classAlias.equals(alias)) { - return t.codeValue; - } - } - return null; - } + private final String codeValue; - public static String getCodeMeaning(String alias) { - for (ProfileItemType t : ProfileItemType.values()) { - if (t.classAlias.equals(alias)) { - return t.codeMeaning; - } - } - return null; - } + private final String codeMeaning; - public Class getProfileClass() { - return profileClass; - } + ProfileItemType(Class profileClass, String alias, String codeValue, String codeMeaning) { + this.profileClass = profileClass; + this.classAlias = alias; + this.codeValue = codeValue; + this.codeMeaning = codeMeaning; + } + + public static ProfileItemType getType(String alias) { + for (ProfileItemType t : ProfileItemType.values()) { + if (t.classAlias.equals(alias)) { + return t; + } + } + return null; + } + + public static String getCodeValue(String alias) { + for (ProfileItemType t : ProfileItemType.values()) { + if (t.classAlias.equals(alias)) { + return t.codeValue; + } + } + return null; + } + + public static String getCodeMeaning(String alias) { + for (ProfileItemType t : ProfileItemType.values()) { + if (t.classAlias.equals(alias)) { + return t.codeMeaning; + } + } + return null; + } + + public Class getProfileClass() { + return profileClass; + } + + public String getClassAlias() { + return classAlias; + } - public String getClassAlias() { - return classAlias; - } } diff --git a/src/main/java/org/karnak/backend/enums/PseudonymType.java b/src/main/java/org/karnak/backend/enums/PseudonymType.java index ace40c8a3..31d232e9b 100644 --- a/src/main/java/org/karnak/backend/enums/PseudonymType.java +++ b/src/main/java/org/karnak/backend/enums/PseudonymType.java @@ -10,18 +10,19 @@ package org.karnak.backend.enums; public enum PseudonymType { - MAINZELLISTE_PID("Pseudonym is generated by mainzelliste"), - MAINZELLISTE_EXTID("Pseudonym that has already been entered manually in mainzelliste"), - CACHE_EXTID("Pseudonym is already store in KARNAK"), - EXTID_IN_TAG("Pseudonym is in a DICOM tag"); - private final String value; + MAINZELLISTE_PID("Pseudonym is generated by mainzelliste"), MAINZELLISTE_EXTID( + "Pseudonym that has already been entered manually in mainzelliste"), CACHE_EXTID( + "Pseudonym is already store in KARNAK"), EXTID_IN_TAG("Pseudonym is in a DICOM tag"); - PseudonymType(String value) { - this.value = value; - } + private final String value; + + PseudonymType(String value) { + this.value = value; + } + + public String getValue() { + return value; + } - public String getValue() { - return value; - } } diff --git a/src/main/java/org/karnak/backend/enums/SecurityRole.java b/src/main/java/org/karnak/backend/enums/SecurityRole.java index 34fed8200..b3ddae84f 100644 --- a/src/main/java/org/karnak/backend/enums/SecurityRole.java +++ b/src/main/java/org/karnak/backend/enums/SecurityRole.java @@ -13,66 +13,61 @@ public enum SecurityRole { - // Role admin - ADMIN_ROLE("ROLE_admin", "admin"), - // Role Investigator - INVESTIGATOR_ROLE("ROLE_investigator", "investigator"), - // Role user - USER_ROLE("ROLE_user", "user"); + // Role admin + ADMIN_ROLE("ROLE_admin", "admin"), + // Role Investigator + INVESTIGATOR_ROLE("ROLE_investigator", "investigator"), + // Role user + USER_ROLE("ROLE_user", "user"); - /** Role of the enum */ - private final String role; + /** Role of the enum */ + private final String role; - /** Type of the enum */ - private final String type; + /** Type of the enum */ + private final String type; - /** - * Constructor - * - * @param role Role of the enum - * @param type Type of the enum - */ - SecurityRole(final String role, final String type) { - this.role = role; - this.type = type; - } + /** + * Constructor + * @param role Role of the enum + * @param type Type of the enum + */ + SecurityRole(final String role, final String type) { + this.role = role; + this.type = type; + } - /** - * Get the enum from the role in parameter - * - * @param role Role of the enum - * @return SecurityRole found - */ - public static SecurityRole fromCode(final String role) { - if (role != null) { - return Arrays.stream(SecurityRole.values()) - .filter(r -> role.trim().equalsIgnoreCase(r.getRole())) - .findFirst() - .orElse(null); - } - return null; - } + /** + * Get the enum from the role in parameter + * @param role Role of the enum + * @return SecurityRole found + */ + public static SecurityRole fromCode(final String role) { + if (role != null) { + return Arrays.stream(SecurityRole.values()).filter(r -> role.trim().equalsIgnoreCase(r.getRole())) + .findFirst().orElse(null); + } + return null; + } - /** - * Getter for code - * - * @return Role of the enum - */ - public String getRole() { - return role; - } + /** + * Getter for code + * @return Role of the enum + */ + public String getRole() { + return role; + } - /** - * Getter for type - * - * @return Type of the enum - */ - public String getType() { - return type; - } + /** + * Getter for type + * @return Type of the enum + */ + public String getType() { + return type; + } + + @Override + public String toString() { + return "SecurityRole{" + "role='" + role + '\'' + "type='" + type + '\'' + '}'; + } - @Override - public String toString() { - return "SecurityRole{" + "role='" + role + '\'' + "type='" + type + '\'' + '}'; - } } diff --git a/src/main/java/org/karnak/backend/enums/TransferStatusType.java b/src/main/java/org/karnak/backend/enums/TransferStatusType.java index ede4bb260..922fa722d 100644 --- a/src/main/java/org/karnak/backend/enums/TransferStatusType.java +++ b/src/main/java/org/karnak/backend/enums/TransferStatusType.java @@ -11,32 +11,31 @@ /** Enum for the transfer status */ public enum TransferStatusType { - ALL(null, "All"), - SENT(true, "Sent"), - NOT_SENT(false, "Not Sent"); - - /** Code of the enum */ - private final Boolean code; - - /** Description of the enum */ - private final String description; - - /** - * Constructor - * - * @param code Code - * @param description Description - */ - TransferStatusType(Boolean code, String description) { - this.code = code; - this.description = description; - } - - public Boolean getCode() { - return code; - } - - public String getDescription() { - return description; - } + + ALL(null, "All"), SENT(true, "Sent"), NOT_SENT(false, "Not Sent"); + + /** Code of the enum */ + private final Boolean code; + + /** Description of the enum */ + private final String description; + + /** + * Constructor + * @param code Code + * @param description Description + */ + TransferStatusType(Boolean code, String description) { + this.code = code; + this.description = description; + } + + public Boolean getCode() { + return code; + } + + public String getDescription() { + return description; + } + } diff --git a/src/main/java/org/karnak/backend/enums/UIDType.java b/src/main/java/org/karnak/backend/enums/UIDType.java index 2992e7a8e..fb075407d 100644 --- a/src/main/java/org/karnak/backend/enums/UIDType.java +++ b/src/main/java/org/karnak/backend/enums/UIDType.java @@ -14,98 +14,89 @@ public enum UIDType { - // Role admin - EXPLICIT_VR_LITTLE_ENDIAN("1.2.840.10008.1.2.1", "Explicit VR - Little Endian"), - JPEG_BASELINE_8BIT( - "1.2.840.10008.1.2.4.50", - "JPEG Baseline (Process 1): Default Transfer Syntax for Lossy JPEG 8 Bit Image Compression"), - JPEG_EXTENDED_12BIT( - "1.2.840.10008.1.2.4.51", - "JPEG Extended (Process 2 & 4): Default Transfer Syntax for Lossy JPEG 12 Bit Image Compression (Process 4 only)"), - JPEG_SPECTRAL_SELECTION_NON_HIERARCHICAL_68( - "1.2.840.10008.1.2.4.53", - "JPEG Spectral Selection, Non-Hierarchical (Process 6 & 8) (Retired)"), - JPEG_FULL_PROGRESSION_NON_HIERARCHICAL_1012( - "1.2.840.10008.1.2.4.55", - "JPEG Full Progression, Non-Hierarchical (Process 10 & 12) (Retired)"), - JPEG_LOSSLESS("1.2.840.10008.1.2.4.57", "JPEG Lossless, Non-Hierarchical (Process 14)"), - JPEG_LOSSLESS_SV1( - "1.2.840.10008.1.2.4.70", - "JPEG Lossless, Non-Hierarchical, First-Order Prediction (Process 14 [Selection Value 1]): Default Transfer Syntax for Lossless JPEG Image Compression"), - JPEG_LS_LOSSLESS("1.2.840.10008.1.2.4.80", "JPEG-LS Lossless Image Compression"), - JPEG_LS_NEAR_LOSSLESS( - "1.2.840.10008.1.2.4.81", "JPEG-LS Lossy (Near-Lossless) Image Compression"), - JPEG_2000_LOSSLESS("1.2.840.10008.1.2.4.90", "JPEG 2000 Image Compression (Lossless Only)"), - JPEG_2000("1.2.840.10008.1.2.4.91", "JPEG 2000 Image Compression"); + // Role admin + EXPLICIT_VR_LITTLE_ENDIAN("1.2.840.10008.1.2.1", "Explicit VR - Little Endian"), JPEG_BASELINE_8BIT( + "1.2.840.10008.1.2.4.50", + "JPEG Baseline (Process 1): Default Transfer Syntax for Lossy JPEG 8 Bit Image Compression"), JPEG_EXTENDED_12BIT( + "1.2.840.10008.1.2.4.51", + "JPEG Extended (Process 2 & 4): Default Transfer Syntax for Lossy JPEG 12 Bit Image Compression (Process 4 only)"), JPEG_SPECTRAL_SELECTION_NON_HIERARCHICAL_68( + "1.2.840.10008.1.2.4.53", + "JPEG Spectral Selection, Non-Hierarchical (Process 6 & 8) (Retired)"), JPEG_FULL_PROGRESSION_NON_HIERARCHICAL_1012( + "1.2.840.10008.1.2.4.55", + "JPEG Full Progression, Non-Hierarchical (Process 10 & 12) (Retired)"), JPEG_LOSSLESS( + "1.2.840.10008.1.2.4.57", + "JPEG Lossless, Non-Hierarchical (Process 14)"), JPEG_LOSSLESS_SV1( + "1.2.840.10008.1.2.4.70", + "JPEG Lossless, Non-Hierarchical, First-Order Prediction (Process 14 [Selection Value 1]): Default Transfer Syntax for Lossless JPEG Image Compression"), JPEG_LS_LOSSLESS( + "1.2.840.10008.1.2.4.80", + "JPEG-LS Lossless Image Compression"), JPEG_LS_NEAR_LOSSLESS( + "1.2.840.10008.1.2.4.81", + "JPEG-LS Lossy (Near-Lossless) Image Compression"), JPEG_2000_LOSSLESS( + "1.2.840.10008.1.2.4.90", + "JPEG 2000 Image Compression (Lossless Only)"), JPEG_2000( + "1.2.840.10008.1.2.4.91", + "JPEG 2000 Image Compression"); - /** Code of the enum */ - private final String code; + /** Code of the enum */ + private final String code; - /** Description of the enum */ - private final String description; + /** Description of the enum */ + private final String description; - /** Default description */ - public static final String DEFAULT_DESCRIPTION = "Keep original transfer syntax"; + /** Default description */ + public static final String DEFAULT_DESCRIPTION = "Keep original transfer syntax"; - /** - * Constructor - * - * @param code Code - * @param description Description - */ - UIDType(String code, String description) { - this.code = code; - this.description = description; - } + /** + * Constructor + * @param code Code + * @param description Description + */ + UIDType(String code, String description) { + this.code = code; + this.description = description; + } - /** - * Get the enum from the role in parameter - * - * @param code Code of the enum - * @return UIDType found - */ - public static UIDType fromCode(final String code) { - if (code != null) { - return Arrays.stream(UIDType.values()) - .filter(u -> code.trim().equalsIgnoreCase(u.getCode())) - .findFirst() - .orElse(null); - } - return null; - } + /** + * Get the enum from the role in parameter + * @param code Code of the enum + * @return UIDType found + */ + public static UIDType fromCode(final String code) { + if (code != null) { + return Arrays.stream(UIDType.values()).filter(u -> code.trim().equalsIgnoreCase(u.getCode())).findFirst() + .orElse(null); + } + return null; + } - /** - * Get the enum from the description in parameter - * - * @param description Description of the enum - * @return UIDType found - */ - public static UIDType fromDescription(final String description) { - if (description != null) { - return Arrays.stream(UIDType.values()) - .filter(u -> description.trim().equalsIgnoreCase(u.getDescription())) - .findFirst() - .orElse(null); - } - return null; - } + /** + * Get the enum from the description in parameter + * @param description Description of the enum + * @return UIDType found + */ + public static UIDType fromDescription(final String description) { + if (description != null) { + return Arrays.stream(UIDType.values()).filter(u -> description.trim().equalsIgnoreCase(u.getDescription())) + .findFirst().orElse(null); + } + return null; + } - public static String descriptionOf(final String code) { - if (code != null) { - Optional uidTypeFound = - Arrays.stream(UIDType.values()) - .filter(u -> code.trim().equalsIgnoreCase(u.getCode())) - .findFirst(); - return uidTypeFound.isPresent() ? uidTypeFound.get().getDescription() : DEFAULT_DESCRIPTION; - } - return DEFAULT_DESCRIPTION; - } + public static String descriptionOf(final String code) { + if (code != null) { + Optional uidTypeFound = Arrays.stream(UIDType.values()) + .filter(u -> code.trim().equalsIgnoreCase(u.getCode())).findFirst(); + return uidTypeFound.isPresent() ? uidTypeFound.get().getDescription() : DEFAULT_DESCRIPTION; + } + return DEFAULT_DESCRIPTION; + } - public String getCode() { - return code; - } + public String getCode() { + return code; + } + + public String getDescription() { + return description; + } - public String getDescription() { - return description; - } } diff --git a/src/main/java/org/karnak/backend/exception/AbortException.java b/src/main/java/org/karnak/backend/exception/AbortException.java index e3c086f73..ee56c1398 100644 --- a/src/main/java/org/karnak/backend/exception/AbortException.java +++ b/src/main/java/org/karnak/backend/exception/AbortException.java @@ -13,25 +13,27 @@ public final class AbortException extends IllegalStateException { - private static final long serialVersionUID = 3993065212756372490L; - private final Abort abort; - - public AbortException(Abort abort, String s) { - super(s); - this.abort = abort; - } - - public AbortException(Abort abort, String string, Exception e) { - super(string, e); - this.abort = abort; - } - - @Override - public String toString() { - return getMessage(); - } - - public Abort getAbort() { - return abort; - } + private static final long serialVersionUID = 3993065212756372490L; + + private final Abort abort; + + public AbortException(Abort abort, String s) { + super(s); + this.abort = abort; + } + + public AbortException(Abort abort, String string, Exception e) { + super(string, e); + this.abort = abort; + } + + @Override + public String toString() { + return getMessage(); + } + + public Abort getAbort() { + return abort; + } + } diff --git a/src/main/java/org/karnak/backend/exception/ModuleNotFoundException.java b/src/main/java/org/karnak/backend/exception/ModuleNotFoundException.java index 559576f10..6f60bdf31 100644 --- a/src/main/java/org/karnak/backend/exception/ModuleNotFoundException.java +++ b/src/main/java/org/karnak/backend/exception/ModuleNotFoundException.java @@ -11,7 +11,8 @@ public class ModuleNotFoundException extends StandardDICOMException { - public ModuleNotFoundException(String message) { - super(message); - } + public ModuleNotFoundException(String message) { + super(message); + } + } diff --git a/src/main/java/org/karnak/backend/exception/SOPNotFoundException.java b/src/main/java/org/karnak/backend/exception/SOPNotFoundException.java index 3d6e4d238..8d88f33cf 100644 --- a/src/main/java/org/karnak/backend/exception/SOPNotFoundException.java +++ b/src/main/java/org/karnak/backend/exception/SOPNotFoundException.java @@ -11,7 +11,8 @@ public class SOPNotFoundException extends StandardDICOMException { - public SOPNotFoundException(String message) { - super(message); - } + public SOPNotFoundException(String message) { + super(message); + } + } diff --git a/src/main/java/org/karnak/backend/exception/StandardDICOMException.java b/src/main/java/org/karnak/backend/exception/StandardDICOMException.java index b3fb6701f..014689b9d 100644 --- a/src/main/java/org/karnak/backend/exception/StandardDICOMException.java +++ b/src/main/java/org/karnak/backend/exception/StandardDICOMException.java @@ -11,7 +11,8 @@ public abstract class StandardDICOMException extends RuntimeException { - public StandardDICOMException(String message) { - super(message); - } + public StandardDICOMException(String message) { + super(message); + } + } diff --git a/src/main/java/org/karnak/backend/model/FileInfo.java b/src/main/java/org/karnak/backend/model/FileInfo.java index 86505e0e1..495ed74de 100644 --- a/src/main/java/org/karnak/backend/model/FileInfo.java +++ b/src/main/java/org/karnak/backend/model/FileInfo.java @@ -11,31 +11,35 @@ public final class FileInfo { - private final String iuid; - private final String cuid; - private final String tsuid; - private final String filename; - - public FileInfo(String filename, String iuid, String cuid, String tsuid) { - this.filename = filename; - this.iuid = iuid; - this.cuid = cuid; - this.tsuid = tsuid; - } - - public String getFilename() { - return filename; - } - - public String getCuid() { - return cuid; - } - - public String getIuid() { - return iuid; - } - - public String getTsuid() { - return tsuid; - } + private final String iuid; + + private final String cuid; + + private final String tsuid; + + private final String filename; + + public FileInfo(String filename, String iuid, String cuid, String tsuid) { + this.filename = filename; + this.iuid = iuid; + this.cuid = cuid; + this.tsuid = tsuid; + } + + public String getFilename() { + return filename; + } + + public String getCuid() { + return cuid; + } + + public String getIuid() { + return iuid; + } + + public String getTsuid() { + return tsuid; + } + } diff --git a/src/main/java/org/karnak/backend/model/Series.java b/src/main/java/org/karnak/backend/model/Series.java index d8779bfe5..14108fd14 100644 --- a/src/main/java/org/karnak/backend/model/Series.java +++ b/src/main/java/org/karnak/backend/model/Series.java @@ -19,79 +19,82 @@ public class Series { - private final String seriesInstanceUID; - private final Map sopInstanceMap; - - private String seriesDescription; - private LocalDateTime seriesDate; - - public Series(String seriesInstanceUID) { - this.seriesInstanceUID = Objects.requireNonNull(seriesInstanceUID, "seriesInstanceUID is null"); - this.sopInstanceMap = new HashMap<>(); - this.seriesDescription = ""; - } - - public String getSeriesInstanceUID() { - return seriesInstanceUID; - } - - public String getSeriesDescription() { - return seriesDescription; - } - - public void setSeriesDescription(String s) { - seriesDescription = s; - } - - public LocalDateTime getSeriesDate() { - return seriesDate; - } - - public void setSeriesDate(LocalDateTime seriesDate) { - this.seriesDate = seriesDate; - } - - public void addSopInstance(SopInstance s) { - SopInstance.addSopInstance(sopInstanceMap, s); - } - - public SopInstance removeSopInstance(String sopUID) { - return SopInstance.removeSopInstance(sopInstanceMap, sopUID); - } - - public SopInstance getSopInstance(String sopUID) { - return SopInstance.getSopInstance(sopInstanceMap, sopUID); - } - - public Set> getEntrySet() { - return sopInstanceMap.entrySet(); - } - - public Collection getSopInstances() { - return sopInstanceMap.values(); - } - - public boolean isEmpty() { - return sopInstanceMap.isEmpty(); - } - - @Override - public int hashCode() { - return 31 + seriesInstanceUID.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - Series other = (Series) obj; - return seriesInstanceUID.equals(other.seriesInstanceUID); - } + private final String seriesInstanceUID; + + private final Map sopInstanceMap; + + private String seriesDescription; + + private LocalDateTime seriesDate; + + public Series(String seriesInstanceUID) { + this.seriesInstanceUID = Objects.requireNonNull(seriesInstanceUID, "seriesInstanceUID is null"); + this.sopInstanceMap = new HashMap<>(); + this.seriesDescription = ""; + } + + public String getSeriesInstanceUID() { + return seriesInstanceUID; + } + + public String getSeriesDescription() { + return seriesDescription; + } + + public void setSeriesDescription(String s) { + seriesDescription = s; + } + + public LocalDateTime getSeriesDate() { + return seriesDate; + } + + public void setSeriesDate(LocalDateTime seriesDate) { + this.seriesDate = seriesDate; + } + + public void addSopInstance(SopInstance s) { + SopInstance.addSopInstance(sopInstanceMap, s); + } + + public SopInstance removeSopInstance(String sopUID) { + return SopInstance.removeSopInstance(sopInstanceMap, sopUID); + } + + public SopInstance getSopInstance(String sopUID) { + return SopInstance.getSopInstance(sopInstanceMap, sopUID); + } + + public Set> getEntrySet() { + return sopInstanceMap.entrySet(); + } + + public Collection getSopInstances() { + return sopInstanceMap.values(); + } + + public boolean isEmpty() { + return sopInstanceMap.isEmpty(); + } + + @Override + public int hashCode() { + return 31 + seriesInstanceUID.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + Series other = (Series) obj; + return seriesInstanceUID.equals(other.seriesInstanceUID); + } + } diff --git a/src/main/java/org/karnak/backend/model/SopInstance.java b/src/main/java/org/karnak/backend/model/SopInstance.java index f36456add..32665c4ad 100644 --- a/src/main/java/org/karnak/backend/model/SopInstance.java +++ b/src/main/java/org/karnak/backend/model/SopInstance.java @@ -14,61 +14,64 @@ public class SopInstance { - private final String sopInstanceUID; - private Integer instanceNumber; - private String sopClassUID; - private boolean sent; - - public SopInstance(String sopInstanceUID) { - this.sopInstanceUID = Objects.requireNonNull(sopInstanceUID, "sopInstanceIUID is null"); - } - - public static void addSopInstance(Map sopInstanceMap, SopInstance s) { - if (s != null && sopInstanceMap != null) { - sopInstanceMap.put(s.getSopInstanceUID(), s); - } - } - - public static SopInstance removeSopInstance( - Map sopInstanceMap, String sopUID) { - if (sopUID == null || sopInstanceMap == null) { - return null; - } - return sopInstanceMap.remove(sopUID); - } - - public static SopInstance getSopInstance(Map sopInstanceMap, String sopUID) { - if (sopUID == null || sopInstanceMap == null) { - return null; - } - return sopInstanceMap.get(sopUID); - } - - public String getSopInstanceUID() { - return sopInstanceUID; - } - - public Integer getInstanceNumber() { - return instanceNumber; - } - - public void setInstanceNumber(Integer instanceNumber) { - this.instanceNumber = instanceNumber; - } - - public String getSopClassUID() { - return sopClassUID; - } - - public void setSopClassUID(String sopClassUID) { - this.sopClassUID = sopClassUID; - } - - public boolean isSent() { - return sent; - } - - public void setSent(boolean sent) { - this.sent = sent; - } + private final String sopInstanceUID; + + private Integer instanceNumber; + + private String sopClassUID; + + private boolean sent; + + public SopInstance(String sopInstanceUID) { + this.sopInstanceUID = Objects.requireNonNull(sopInstanceUID, "sopInstanceIUID is null"); + } + + public static void addSopInstance(Map sopInstanceMap, SopInstance s) { + if (s != null && sopInstanceMap != null) { + sopInstanceMap.put(s.getSopInstanceUID(), s); + } + } + + public static SopInstance removeSopInstance(Map sopInstanceMap, String sopUID) { + if (sopUID == null || sopInstanceMap == null) { + return null; + } + return sopInstanceMap.remove(sopUID); + } + + public static SopInstance getSopInstance(Map sopInstanceMap, String sopUID) { + if (sopUID == null || sopInstanceMap == null) { + return null; + } + return sopInstanceMap.get(sopUID); + } + + public String getSopInstanceUID() { + return sopInstanceUID; + } + + public Integer getInstanceNumber() { + return instanceNumber; + } + + public void setInstanceNumber(Integer instanceNumber) { + this.instanceNumber = instanceNumber; + } + + public String getSopClassUID() { + return sopClassUID; + } + + public void setSopClassUID(String sopClassUID) { + this.sopClassUID = sopClassUID; + } + + public boolean isSent() { + return sent; + } + + public void setSent(boolean sent) { + this.sent = sent; + } + } diff --git a/src/main/java/org/karnak/backend/model/SourceNode.java b/src/main/java/org/karnak/backend/model/SourceNode.java index a9f7197ee..9176b9ee8 100644 --- a/src/main/java/org/karnak/backend/model/SourceNode.java +++ b/src/main/java/org/karnak/backend/model/SourceNode.java @@ -13,39 +13,41 @@ public class SourceNode { - private final String forwardAETitle; - private final DicomNode sourceNode; - - public SourceNode(String forwardAETitle, DicomNode sourceNode) { - this.forwardAETitle = forwardAETitle; - this.sourceNode = sourceNode; - } - - public String getForwardAETitle() { - return forwardAETitle; - } - - public DicomNode getSourceNode() { - return sourceNode; - } - - @Override - public int hashCode() { - return 31 + forwardAETitle.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - SourceNode other = (SourceNode) obj; - return forwardAETitle.equals(other.forwardAETitle); - } + private final String forwardAETitle; + + private final DicomNode sourceNode; + + public SourceNode(String forwardAETitle, DicomNode sourceNode) { + this.forwardAETitle = forwardAETitle; + this.sourceNode = sourceNode; + } + + public String getForwardAETitle() { + return forwardAETitle; + } + + public DicomNode getSourceNode() { + return sourceNode; + } + + @Override + public int hashCode() { + return 31 + forwardAETitle.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + SourceNode other = (SourceNode) obj; + return forwardAETitle.equals(other.forwardAETitle); + } + } diff --git a/src/main/java/org/karnak/backend/model/Study.java b/src/main/java/org/karnak/backend/model/Study.java index 6f7aa696a..b1f67f6fa 100644 --- a/src/main/java/org/karnak/backend/model/Study.java +++ b/src/main/java/org/karnak/backend/model/Study.java @@ -19,123 +19,130 @@ public class Study { - private final String studyInstanceUID; - private final Map seriesMap; - private String patientID; - private String[] otherPatientIDs; - private String studyDescription; - private String accessionNumber; - private LocalDateTime studyDate; - private long timeStamp; - - public Study(String studyInstanceUID, String patientID) { - this.studyInstanceUID = - Objects.requireNonNull(studyInstanceUID, "studyInstanceUID cannot be null!"); - this.patientID = patientID == null ? "" : patientID; - this.studyDescription = ""; - this.seriesMap = new HashMap<>(); - } - - public String getStudyInstanceUID() { - return studyInstanceUID; - } - - public String getPatientID() { - return patientID; - } - - public void setPatientID(String patientID) { - this.patientID = patientID; - } - - public String getStudyDescription() { - return studyDescription; - } - - public void setStudyDescription(String studyDesc) { - this.studyDescription = studyDesc; - } - - public LocalDateTime getStudyDate() { - return studyDate; - } - - public void setStudyDate(LocalDateTime studyDate) { - this.studyDate = studyDate; - } - - public void addSeries(Series s) { - if (s != null) { - seriesMap.put(s.getSeriesInstanceUID(), s); - } - } - - public Series removeSeries(String seriesUID) { - return seriesMap.remove(seriesUID); - } - - public boolean isEmpty() { - for (Series s : seriesMap.values()) { - if (!s.isEmpty()) { - return false; - } - } - return true; - } - - public Series getSeries(String seriesUID) { - return seriesMap.get(seriesUID); - } - - public Collection getSeries() { - return seriesMap.values(); - } - - public Set> getEntrySet() { - return seriesMap.entrySet(); - } - - @Override - public int hashCode() { - return 31 + studyInstanceUID.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - Study other = (Study) obj; - return studyInstanceUID.equals(other.studyInstanceUID); - } - - public long getTimeStamp() { - return timeStamp; - } - - public void setTimeStamp(long timeStamp) { - this.timeStamp = timeStamp; - } - - public String[] getOtherPatientIDs() { - return otherPatientIDs; - } - - public void setOtherPatientIDs(String[] otherPatientIDs) { - this.otherPatientIDs = otherPatientIDs; - } - - public String getAccessionNumber() { - return accessionNumber; - } - - public void setAccessionNumber(String accessionNumber) { - this.accessionNumber = accessionNumber; - } + private final String studyInstanceUID; + + private final Map seriesMap; + + private String patientID; + + private String[] otherPatientIDs; + + private String studyDescription; + + private String accessionNumber; + + private LocalDateTime studyDate; + + private long timeStamp; + + public Study(String studyInstanceUID, String patientID) { + this.studyInstanceUID = Objects.requireNonNull(studyInstanceUID, "studyInstanceUID cannot be null!"); + this.patientID = patientID == null ? "" : patientID; + this.studyDescription = ""; + this.seriesMap = new HashMap<>(); + } + + public String getStudyInstanceUID() { + return studyInstanceUID; + } + + public String getPatientID() { + return patientID; + } + + public void setPatientID(String patientID) { + this.patientID = patientID; + } + + public String getStudyDescription() { + return studyDescription; + } + + public void setStudyDescription(String studyDesc) { + this.studyDescription = studyDesc; + } + + public LocalDateTime getStudyDate() { + return studyDate; + } + + public void setStudyDate(LocalDateTime studyDate) { + this.studyDate = studyDate; + } + + public void addSeries(Series s) { + if (s != null) { + seriesMap.put(s.getSeriesInstanceUID(), s); + } + } + + public Series removeSeries(String seriesUID) { + return seriesMap.remove(seriesUID); + } + + public boolean isEmpty() { + for (Series s : seriesMap.values()) { + if (!s.isEmpty()) { + return false; + } + } + return true; + } + + public Series getSeries(String seriesUID) { + return seriesMap.get(seriesUID); + } + + public Collection getSeries() { + return seriesMap.values(); + } + + public Set> getEntrySet() { + return seriesMap.entrySet(); + } + + @Override + public int hashCode() { + return 31 + studyInstanceUID.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + Study other = (Study) obj; + return studyInstanceUID.equals(other.studyInstanceUID); + } + + public long getTimeStamp() { + return timeStamp; + } + + public void setTimeStamp(long timeStamp) { + this.timeStamp = timeStamp; + } + + public String[] getOtherPatientIDs() { + return otherPatientIDs; + } + + public void setOtherPatientIDs(String[] otherPatientIDs) { + this.otherPatientIDs = otherPatientIDs; + } + + public String getAccessionNumber() { + return accessionNumber; + } + + public void setAccessionNumber(String accessionNumber) { + this.accessionNumber = accessionNumber; + } + } diff --git a/src/main/java/org/karnak/backend/model/action/AbstractAction.java b/src/main/java/org/karnak/backend/model/action/AbstractAction.java index 928218162..e7a87a8b8 100644 --- a/src/main/java/org/karnak/backend/model/action/AbstractAction.java +++ b/src/main/java/org/karnak/backend/model/action/AbstractAction.java @@ -18,89 +18,99 @@ import org.weasis.core.util.StringUtil; public abstract class AbstractAction implements ActionItem { - protected static final Logger LOGGER = LoggerFactory.getLogger(AbstractAction.class); - protected static final Marker CLINICAL_MARKER = MarkerFactory.getMarker("CLINICAL"); - protected static final String PATTERN_WITH_INOUT = - "SOPInstanceUID_OLD={} TAG={} ACTION={} OLD={} NEW={}"; - protected static final String PATTERN_WITH_IN = "SOPInstanceUID_OLD={} TAG={} ACTION={} OLD={}"; - protected static final String ADD_METHOD = "a"; - - protected final String symbol; - protected String dummyValue; - protected int newTag; - protected VR vr; - - protected AbstractAction(String symbol) { - this.symbol = symbol; - this.dummyValue = null; - this.vr = null; - } - - protected AbstractAction(String symbol, String dummyValue) { - this.symbol = symbol; - this.dummyValue = dummyValue; - this.vr = null; - } - - protected AbstractAction(String symbol, VR vr, String dummyValue) { - this.symbol = symbol; - this.vr = vr; - this.dummyValue = dummyValue; - } - - protected AbstractAction(String symbol, int newTag, VR vr, String dummyValue) { - this.symbol = symbol; - this.newTag = newTag; - this.vr = vr; - this.dummyValue = dummyValue; - } - - public static AbstractAction convertAction(String action) { - if (action == null) { - return null; - } - return switch (action) { - case "Z" -> new ReplaceNull("Z"); - case "X" -> new Remove("X"); - case "K" -> new Keep("K"); - case "U" -> new UID("U"); - case "DDum" -> new DefaultDummy("DDum"); - case "D" -> new Replace("D"); - default -> null; - }; - } - - public String getSymbol() { - return symbol; - } - - public String getDummyValue() { - return dummyValue; - } - - public void setDummyValue(String dummyValue) { - this.dummyValue = dummyValue; - } - - public VR getVr() { - return vr; - } - - public void setVr(VR vr) { - this.vr = vr; - } - - public static String getStringValue(Attributes dcm, int tag) { - if (dcm != null) { - VR vr = dcm.getVR(tag); - if (vr.isInlineBinary()) { - return "Binary Data"; - } else if (vr == VR.SQ) { - return "Sequence Data"; - } else { - return dcm.getString(tag, StringUtil.EMPTY_STRING); - } - } - return StringUtil.EMPTY_STRING; - } + + protected static final Logger LOGGER = LoggerFactory.getLogger(AbstractAction.class); + + protected static final Marker CLINICAL_MARKER = MarkerFactory.getMarker("CLINICAL"); + + protected static final String PATTERN_WITH_INOUT = "SOPInstanceUID_OLD={} TAG={} ACTION={} OLD={} NEW={}"; + + protected static final String PATTERN_WITH_IN = "SOPInstanceUID_OLD={} TAG={} ACTION={} OLD={}"; + + protected static final String ADD_METHOD = "a"; + + protected final String symbol; + + protected String dummyValue; + + protected int newTag; + + protected VR vr; + + protected AbstractAction(String symbol) { + this.symbol = symbol; + this.dummyValue = null; + this.vr = null; + } + + protected AbstractAction(String symbol, String dummyValue) { + this.symbol = symbol; + this.dummyValue = dummyValue; + this.vr = null; + } + + protected AbstractAction(String symbol, VR vr, String dummyValue) { + this.symbol = symbol; + this.vr = vr; + this.dummyValue = dummyValue; + } + + protected AbstractAction(String symbol, int newTag, VR vr, String dummyValue) { + this.symbol = symbol; + this.newTag = newTag; + this.vr = vr; + this.dummyValue = dummyValue; + } + + public static AbstractAction convertAction(String action) { + if (action == null) { + return null; + } + return switch (action) { + case "Z" -> new ReplaceNull("Z"); + case "X" -> new Remove("X"); + case "K" -> new Keep("K"); + case "U" -> new UID("U"); + case "DDum" -> new DefaultDummy("DDum"); + case "D" -> new Replace("D"); + default -> null; + }; + } + + public String getSymbol() { + return symbol; + } + + public String getDummyValue() { + return dummyValue; + } + + public void setDummyValue(String dummyValue) { + this.dummyValue = dummyValue; + } + + public VR getVr() { + return vr; + } + + public void setVr(VR vr) { + this.vr = vr; + } + + public static String getStringValue(Attributes dcm, int tag) { + if (dcm != null) { + VR vr = dcm.getVR(tag); + if (vr.isInlineBinary()) { + return "Binary Data"; + } + else if (vr == VR.SQ) { + return "Sequence Data"; + } + else { + return dcm.getString(tag, StringUtil.EMPTY_STRING); + } + } + return StringUtil.EMPTY_STRING; + } + } diff --git a/src/main/java/org/karnak/backend/model/action/ActionItem.java b/src/main/java/org/karnak/backend/model/action/ActionItem.java index d1e7a7195..fdf4550c4 100644 --- a/src/main/java/org/karnak/backend/model/action/ActionItem.java +++ b/src/main/java/org/karnak/backend/model/action/ActionItem.java @@ -15,15 +15,16 @@ public interface ActionItem { - String getSymbol(); + String getSymbol(); - String getDummyValue(); + String getDummyValue(); - void setDummyValue(String dummyValue); + void setDummyValue(String dummyValue); - VR getVr(); + VR getVr(); - void setVr(VR vr); + void setVr(VR vr); + + void execute(Attributes dcm, int tag, HMAC hmac); - void execute(Attributes dcm, int tag, HMAC hmac); } diff --git a/src/main/java/org/karnak/backend/model/action/Add.java b/src/main/java/org/karnak/backend/model/action/Add.java index 160983e33..a42cc48d1 100644 --- a/src/main/java/org/karnak/backend/model/action/Add.java +++ b/src/main/java/org/karnak/backend/model/action/Add.java @@ -17,28 +17,24 @@ public class Add extends AbstractAction { - public Add(String symbol, int newTag, VR vr, String dummyValue) { - super(symbol, newTag, vr, dummyValue); - } + public Add(String symbol, int newTag, VR vr, String dummyValue) { + super(symbol, newTag, vr, dummyValue); + } - @Override - public void execute(Attributes dcm, int tag, HMAC hmac) { - if (LOGGER.isTraceEnabled()) { - String tagValueIn = AbstractAction.getStringValue(dcm, newTag); - LOGGER.trace( - CLINICAL_MARKER, - PATTERN_WITH_INOUT, - MDC.get("SOPInstanceUID"), - TagUtils.toString(newTag), - symbol, - tagValueIn, - dummyValue); - } + @Override + public void execute(Attributes dcm, int tag, HMAC hmac) { + if (LOGGER.isTraceEnabled()) { + String tagValueIn = AbstractAction.getStringValue(dcm, newTag); + LOGGER.trace(CLINICAL_MARKER, PATTERN_WITH_INOUT, MDC.get("SOPInstanceUID"), TagUtils.toString(newTag), + symbol, tagValueIn, dummyValue); + } + + if (dummyValue != null) { + dcm.setString(newTag, vr, dummyValue); + } + else { + dcm.setNull(newTag, vr); + } + } - if (dummyValue != null) { - dcm.setString(newTag, vr, dummyValue); - } else { - dcm.setNull(newTag, vr); - } - } } diff --git a/src/main/java/org/karnak/backend/model/action/DefaultDummy.java b/src/main/java/org/karnak/backend/model/action/DefaultDummy.java index 6a9f14363..5c183b7b6 100644 --- a/src/main/java/org/karnak/backend/model/action/DefaultDummy.java +++ b/src/main/java/org/karnak/backend/model/action/DefaultDummy.java @@ -17,28 +17,28 @@ public class DefaultDummy extends AbstractAction { - static final List argumentEntities = - List.of(new ArgumentEntity("max_days", "365"), new ArgumentEntity("max_seconds", "86400")); + static final List argumentEntities = List.of(new ArgumentEntity("max_days", "365"), + new ArgumentEntity("max_seconds", "86400")); - public DefaultDummy(String symbol) { - super(symbol); - } + public DefaultDummy(String symbol) { + super(symbol); + } - public DefaultDummy(String symbol, String dummyValue) { - super(symbol, dummyValue); - } + public DefaultDummy(String symbol, String dummyValue) { + super(symbol, dummyValue); + } + + @Override + public void execute(Attributes dcm, int tag, HMAC hmac) { + String defaultDummyValue = switch (dcm.getVR(tag)) { + case AE, CS, LO, LT, PN, SH, ST, UN, UT, UC, UR -> "UNKNOWN"; + case DS, IS -> "0"; + case AS, DA, DT, TM -> ShiftRangeDate.shift(dcm, tag, argumentEntities, hmac); + case UI -> hmac.uidHash(dcm.getString(tag)); + default -> null; + }; + ActionItem replace = new Replace(symbol, defaultDummyValue); + replace.execute(dcm, tag, hmac); + } - @Override - public void execute(Attributes dcm, int tag, HMAC hmac) { - String defaultDummyValue = - switch (dcm.getVR(tag)) { - case AE, CS, LO, LT, PN, SH, ST, UN, UT, UC, UR -> "UNKNOWN"; - case DS, IS -> "0"; - case AS, DA, DT, TM -> ShiftRangeDate.shift(dcm, tag, argumentEntities, hmac); - case UI -> hmac.uidHash(dcm.getString(tag)); - default -> null; - }; - ActionItem replace = new Replace(symbol, defaultDummyValue); - replace.execute(dcm, tag, hmac); - } } diff --git a/src/main/java/org/karnak/backend/model/action/Keep.java b/src/main/java/org/karnak/backend/model/action/Keep.java index c9b3ac5a9..61fd96eab 100644 --- a/src/main/java/org/karnak/backend/model/action/Keep.java +++ b/src/main/java/org/karnak/backend/model/action/Keep.java @@ -16,21 +16,17 @@ public class Keep extends AbstractAction { - public Keep(String symbol) { - super(symbol); - } + public Keep(String symbol) { + super(symbol); + } + + @Override + public void execute(Attributes dcm, int tag, HMAC hmac) { + if (LOGGER.isTraceEnabled()) { + String tagValueIn = AbstractAction.getStringValue(dcm, tag); + LOGGER.trace(CLINICAL_MARKER, PATTERN_WITH_IN, MDC.get("SOPInstanceUID"), TagUtils.toString(tag), symbol, + tagValueIn); + } + } - @Override - public void execute(Attributes dcm, int tag, HMAC hmac) { - if (LOGGER.isTraceEnabled()) { - String tagValueIn = AbstractAction.getStringValue(dcm, tag); - LOGGER.trace( - CLINICAL_MARKER, - PATTERN_WITH_IN, - MDC.get("SOPInstanceUID"), - TagUtils.toString(tag), - symbol, - tagValueIn); - } - } } diff --git a/src/main/java/org/karnak/backend/model/action/MultipleActions.java b/src/main/java/org/karnak/backend/model/action/MultipleActions.java index 7ddf69388..69d4462ec 100644 --- a/src/main/java/org/karnak/backend/model/action/MultipleActions.java +++ b/src/main/java/org/karnak/backend/model/action/MultipleActions.java @@ -24,153 +24,153 @@ import org.slf4j.LoggerFactory; public class MultipleActions extends AbstractAction { - private static final Logger LOGGER = LoggerFactory.getLogger(MultipleActions.class); - - final StandardDICOM standardDICOM; - final ActionItem defaultDummyValue; - final ActionItem actionUID; - final ActionItem actionReplaceNull; - final ActionItem actionRemove; - final ActionItem actionKeep; - - public MultipleActions(String symbol) { - super(symbol); - standardDICOM = AppConfig.getInstance().getStandardDICOM(); - defaultDummyValue = new DefaultDummy(symbol); - actionUID = new UID("U"); - actionReplaceNull = new ReplaceNull("Z"); - actionRemove = new Remove("X"); - actionKeep = new Keep("K"); - } - - @Override - public void execute(Attributes dcm, int tag, HMAC hmac) { - String sopUID = MetadataDICOMObject.getValue(dcm, Tag.SOPClassUID); - String tagPath = MetadataDICOMObject.getTagPath(dcm, tag); - try { - List moduleAttributes = standardDICOM.getAttributesBySOP(sopUID, tagPath); - if (moduleAttributes.size() == 1) { - String currentType = moduleAttributes.get(0).getType(); - ActionItem actionItem = chooseAction(sopUID, currentType); - actionItem.execute(dcm, tag, hmac); - } else if (moduleAttributes.size() > 1) { - ActionItem action = multipleAttributes(sopUID, moduleAttributes); - action.execute(dcm, tag, hmac); - } else { - ActionItem action = defaultAction(); - action.execute(dcm, tag, hmac); - LOGGER.warn( - "Cannot find the attribute {} in the SOP {}. The strictest action will be chosen ({}).", - tagPath, - sopUID, - symbol); - } - } catch (StandardDICOMException standardDICOMException) { - ActionItem action = defaultAction(); - action.execute(dcm, tag, hmac); - LOGGER.warn( - "Cannot execute the action {} with the SOP {} and the attribute {}. The strictest action will be chosen.", - symbol, - sopUID, - tagPath, - standardDICOMException); - } - } - - private ActionItem multipleAttributes(String sopUID, List moduleAttributes) { - List mandatoryModuleAttributes = - getMandatoryAttributes(sopUID, moduleAttributes); - - if (mandatoryModuleAttributes.isEmpty()) { - String currentType = ModuleAttribute.getStrictedType(moduleAttributes); - return chooseAction(sopUID, currentType); - } - - if (mandatoryModuleAttributes.size() == 1) { - String currentType = mandatoryModuleAttributes.get(0).getType(); - return chooseAction(sopUID, currentType); - } - - String currentType = ModuleAttribute.getStrictedType(mandatoryModuleAttributes); - return chooseAction(sopUID, currentType); - } - - private List getMandatoryAttributes( - String sopUID, List moduleAttributes) { - List mandatoryModuleAttributes = new ArrayList<>(); - moduleAttributes.forEach( - attribute -> { - Module module = - standardDICOM.getModuleByModuleID(sopUID, attribute.getModuleId()).orElse(null); - if (module != null && Module.moduleIsMandatory(module)) { - mandatoryModuleAttributes.add(attribute); - } - }); - return mandatoryModuleAttributes; - } - - private ActionItem chooseAction(String sopUID, String currentType) { - return switch (symbol) { - case "Z/D" -> dummyOrReplaceNull(currentType); - case "X/D" -> dummyOrRemove(currentType); - case "X/Z/D" -> dummyOrReplaceNullOrRemove(currentType); - case "X/Z" -> replaceNullOrRemove(currentType); - case "X/Z/U", "X/Z/U*" -> uidReplaceNullOrRemove(currentType); - default -> defaultDummyValue; - }; - } - - private ActionItem defaultAction() { - return switch (symbol) { - case "X/Z" -> actionReplaceNull; - case "X/Z/U", "X/Z/U*" -> actionUID; - default -> defaultDummyValue; - }; - } - - private ActionItem dummyOrReplaceNull(String currentType) { - if (currentType.equals("1") || currentType.equals("1C")) { - return defaultDummyValue; - } - return actionReplaceNull; - } - - private ActionItem dummyOrRemove(String currentType) { - if (currentType.equals("3")) { - return actionRemove; - } - return defaultDummyValue; - } - - private ActionItem dummyOrReplaceNullOrRemove(String currentType) { - if (currentType.equals("1") || currentType.equals("1C")) { - return defaultDummyValue; - } - if (currentType.equals("2") || currentType.equals("2C")) { - return actionReplaceNull; - } - return actionRemove; - } - - private ActionItem replaceNullOrRemove(String currentType) { - /* TODO: throw exception ? - if (currentType.equals("1") || currentType.equals("1C")) { - throw new Exception(For the current SOP, the tag must type 1. Impossible to execute and respect the standard); - } - */ - if (currentType.equals("2") || currentType.equals("2C")) { - return actionReplaceNull; - } - return actionRemove; - } - - private ActionItem uidReplaceNullOrRemove(String currentType) { - if (currentType.equals("1") || currentType.equals("1C")) { - return actionUID; - } - if (currentType.equals("2") || currentType.equals("2C")) { - return actionReplaceNull; - } - return actionRemove; - } + + private static final Logger LOGGER = LoggerFactory.getLogger(MultipleActions.class); + + final StandardDICOM standardDICOM; + + final ActionItem defaultDummyValue; + + final ActionItem actionUID; + + final ActionItem actionReplaceNull; + + final ActionItem actionRemove; + + final ActionItem actionKeep; + + public MultipleActions(String symbol) { + super(symbol); + standardDICOM = AppConfig.getInstance().getStandardDICOM(); + defaultDummyValue = new DefaultDummy(symbol); + actionUID = new UID("U"); + actionReplaceNull = new ReplaceNull("Z"); + actionRemove = new Remove("X"); + actionKeep = new Keep("K"); + } + + @Override + public void execute(Attributes dcm, int tag, HMAC hmac) { + String sopUID = MetadataDICOMObject.getValue(dcm, Tag.SOPClassUID); + String tagPath = MetadataDICOMObject.getTagPath(dcm, tag); + try { + List moduleAttributes = standardDICOM.getAttributesBySOP(sopUID, tagPath); + if (moduleAttributes.size() == 1) { + String currentType = moduleAttributes.get(0).getType(); + ActionItem actionItem = chooseAction(sopUID, currentType); + actionItem.execute(dcm, tag, hmac); + } + else if (moduleAttributes.size() > 1) { + ActionItem action = multipleAttributes(sopUID, moduleAttributes); + action.execute(dcm, tag, hmac); + } + else { + ActionItem action = defaultAction(); + action.execute(dcm, tag, hmac); + LOGGER.warn("Cannot find the attribute {} in the SOP {}. The strictest action will be chosen ({}).", + tagPath, sopUID, symbol); + } + } + catch (StandardDICOMException standardDICOMException) { + ActionItem action = defaultAction(); + action.execute(dcm, tag, hmac); + LOGGER.warn( + "Cannot execute the action {} with the SOP {} and the attribute {}. The strictest action will be chosen.", + symbol, sopUID, tagPath, standardDICOMException); + } + } + + private ActionItem multipleAttributes(String sopUID, List moduleAttributes) { + List mandatoryModuleAttributes = getMandatoryAttributes(sopUID, moduleAttributes); + + if (mandatoryModuleAttributes.isEmpty()) { + String currentType = ModuleAttribute.getStrictedType(moduleAttributes); + return chooseAction(sopUID, currentType); + } + + if (mandatoryModuleAttributes.size() == 1) { + String currentType = mandatoryModuleAttributes.get(0).getType(); + return chooseAction(sopUID, currentType); + } + + String currentType = ModuleAttribute.getStrictedType(mandatoryModuleAttributes); + return chooseAction(sopUID, currentType); + } + + private List getMandatoryAttributes(String sopUID, List moduleAttributes) { + List mandatoryModuleAttributes = new ArrayList<>(); + moduleAttributes.forEach(attribute -> { + Module module = standardDICOM.getModuleByModuleID(sopUID, attribute.getModuleId()).orElse(null); + if (module != null && Module.moduleIsMandatory(module)) { + mandatoryModuleAttributes.add(attribute); + } + }); + return mandatoryModuleAttributes; + } + + private ActionItem chooseAction(String sopUID, String currentType) { + return switch (symbol) { + case "Z/D" -> dummyOrReplaceNull(currentType); + case "X/D" -> dummyOrRemove(currentType); + case "X/Z/D" -> dummyOrReplaceNullOrRemove(currentType); + case "X/Z" -> replaceNullOrRemove(currentType); + case "X/Z/U", "X/Z/U*" -> uidReplaceNullOrRemove(currentType); + default -> defaultDummyValue; + }; + } + + private ActionItem defaultAction() { + return switch (symbol) { + case "X/Z" -> actionReplaceNull; + case "X/Z/U", "X/Z/U*" -> actionUID; + default -> defaultDummyValue; + }; + } + + private ActionItem dummyOrReplaceNull(String currentType) { + if (currentType.equals("1") || currentType.equals("1C")) { + return defaultDummyValue; + } + return actionReplaceNull; + } + + private ActionItem dummyOrRemove(String currentType) { + if (currentType.equals("3")) { + return actionRemove; + } + return defaultDummyValue; + } + + private ActionItem dummyOrReplaceNullOrRemove(String currentType) { + if (currentType.equals("1") || currentType.equals("1C")) { + return defaultDummyValue; + } + if (currentType.equals("2") || currentType.equals("2C")) { + return actionReplaceNull; + } + return actionRemove; + } + + private ActionItem replaceNullOrRemove(String currentType) { + /* + * TODO: throw exception ? if (currentType.equals("1") || + * currentType.equals("1C")) { throw new Exception(For the current SOP, the tag + * must type 1. Impossible to execute and respect the standard); } + */ + if (currentType.equals("2") || currentType.equals("2C")) { + return actionReplaceNull; + } + return actionRemove; + } + + private ActionItem uidReplaceNullOrRemove(String currentType) { + if (currentType.equals("1") || currentType.equals("1C")) { + return actionUID; + } + if (currentType.equals("2") || currentType.equals("2C")) { + return actionReplaceNull; + } + return actionRemove; + } + } diff --git a/src/main/java/org/karnak/backend/model/action/Remove.java b/src/main/java/org/karnak/backend/model/action/Remove.java index de4a3f373..7e5ada3cb 100644 --- a/src/main/java/org/karnak/backend/model/action/Remove.java +++ b/src/main/java/org/karnak/backend/model/action/Remove.java @@ -16,22 +16,18 @@ public class Remove extends AbstractAction { - public Remove(String symbol) { - super(symbol); - } + public Remove(String symbol) { + super(symbol); + } + + @Override + public void execute(Attributes dcm, int tag, HMAC hmac) { + if (LOGGER.isTraceEnabled()) { + String tagValueIn = AbstractAction.getStringValue(dcm, tag); + LOGGER.trace(CLINICAL_MARKER, PATTERN_WITH_IN, MDC.get("SOPInstanceUID"), TagUtils.toString(tag), symbol, + tagValueIn); + } + dcm.remove(tag); + } - @Override - public void execute(Attributes dcm, int tag, HMAC hmac) { - if (LOGGER.isTraceEnabled()) { - String tagValueIn = AbstractAction.getStringValue(dcm, tag); - LOGGER.trace( - CLINICAL_MARKER, - PATTERN_WITH_IN, - MDC.get("SOPInstanceUID"), - TagUtils.toString(tag), - symbol, - tagValueIn); - } - dcm.remove(tag); - } } diff --git a/src/main/java/org/karnak/backend/model/action/Replace.java b/src/main/java/org/karnak/backend/model/action/Replace.java index 668820671..e9d036a96 100644 --- a/src/main/java/org/karnak/backend/model/action/Replace.java +++ b/src/main/java/org/karnak/backend/model/action/Replace.java @@ -16,32 +16,28 @@ public class Replace extends AbstractAction { - public Replace(String symbol) { - super(symbol); - } + public Replace(String symbol) { + super(symbol); + } - public Replace(String symbol, String dummyValue) { - super(symbol, dummyValue); - } + public Replace(String symbol, String dummyValue) { + super(symbol, dummyValue); + } - @Override - public void execute(Attributes dcm, int tag, HMAC hmac) { - if (LOGGER.isTraceEnabled()) { - String tagValueIn = AbstractAction.getStringValue(dcm, tag); - LOGGER.trace( - CLINICAL_MARKER, - PATTERN_WITH_INOUT, - MDC.get("SOPInstanceUID"), - TagUtils.toString(tag), - symbol, - tagValueIn, - dummyValue); - } + @Override + public void execute(Attributes dcm, int tag, HMAC hmac) { + if (LOGGER.isTraceEnabled()) { + String tagValueIn = AbstractAction.getStringValue(dcm, tag); + LOGGER.trace(CLINICAL_MARKER, PATTERN_WITH_INOUT, MDC.get("SOPInstanceUID"), TagUtils.toString(tag), symbol, + tagValueIn, dummyValue); + } + + if (dummyValue != null) { + dcm.setString(tag, dcm.getVR(tag), dummyValue); + } + else { + dcm.setNull(tag, dcm.getVR(tag)); + } + } - if (dummyValue != null) { - dcm.setString(tag, dcm.getVR(tag), dummyValue); - } else { - dcm.setNull(tag, dcm.getVR(tag)); - } - } } diff --git a/src/main/java/org/karnak/backend/model/action/ReplaceNull.java b/src/main/java/org/karnak/backend/model/action/ReplaceNull.java index 8baf4d789..1e68e4c59 100644 --- a/src/main/java/org/karnak/backend/model/action/ReplaceNull.java +++ b/src/main/java/org/karnak/backend/model/action/ReplaceNull.java @@ -16,23 +16,18 @@ public class ReplaceNull extends AbstractAction { - public ReplaceNull(String symbol) { - super(symbol); - } + public ReplaceNull(String symbol) { + super(symbol); + } + + @Override + public void execute(Attributes dcm, int tag, HMAC hmac) { + if (LOGGER.isTraceEnabled()) { + String tagValueIn = AbstractAction.getStringValue(dcm, tag); + LOGGER.trace(CLINICAL_MARKER, PATTERN_WITH_INOUT, MDC.get("SOPInstanceUID"), TagUtils.toString(tag), symbol, + tagValueIn, null); + } + dcm.setNull(tag, dcm.getVR(tag)); + } - @Override - public void execute(Attributes dcm, int tag, HMAC hmac) { - if (LOGGER.isTraceEnabled()) { - String tagValueIn = AbstractAction.getStringValue(dcm, tag); - LOGGER.trace( - CLINICAL_MARKER, - PATTERN_WITH_INOUT, - MDC.get("SOPInstanceUID"), - TagUtils.toString(tag), - symbol, - tagValueIn, - null); - } - dcm.setNull(tag, dcm.getVR(tag)); - } } diff --git a/src/main/java/org/karnak/backend/model/action/UID.java b/src/main/java/org/karnak/backend/model/action/UID.java index 770443656..19231e80b 100644 --- a/src/main/java/org/karnak/backend/model/action/UID.java +++ b/src/main/java/org/karnak/backend/model/action/UID.java @@ -17,27 +17,22 @@ public class UID extends AbstractAction { - public UID(String symbol) { - super(symbol); - } + public UID(String symbol) { + super(symbol); + } + + @Override + public void execute(Attributes dcm, int tag, HMAC hmac) { + String uidValue = dcm.getString(tag); + String uidHashed = null; + if (uidValue != null) { + uidHashed = hmac.uidHash(uidValue); + dcm.setString(tag, VR.UI, uidHashed); + } + if (LOGGER.isTraceEnabled()) { + LOGGER.trace(CLINICAL_MARKER, PATTERN_WITH_INOUT, MDC.get("SOPInstanceUID"), TagUtils.toString(tag), symbol, + uidValue, uidHashed); + } + } - @Override - public void execute(Attributes dcm, int tag, HMAC hmac) { - String uidValue = dcm.getString(tag); - String uidHashed = null; - if (uidValue != null) { - uidHashed = hmac.uidHash(uidValue); - dcm.setString(tag, VR.UI, uidHashed); - } - if (LOGGER.isTraceEnabled()) { - LOGGER.trace( - CLINICAL_MARKER, - PATTERN_WITH_INOUT, - MDC.get("SOPInstanceUID"), - TagUtils.toString(tag), - symbol, - uidValue, - uidHashed); - } - } } diff --git a/src/main/java/org/karnak/backend/model/dicom/ConfigNode.java b/src/main/java/org/karnak/backend/model/dicom/ConfigNode.java index d872365ba..e8b555e91 100644 --- a/src/main/java/org/karnak/backend/model/dicom/ConfigNode.java +++ b/src/main/java/org/karnak/backend/model/dicom/ConfigNode.java @@ -15,48 +15,50 @@ public class ConfigNode { - private String name; - private DicomNode calledNode; - - public ConfigNode(String name, DicomNode calledNode) { - this.name = Objects.requireNonNull(name); - this.calledNode = Objects.requireNonNull(calledNode); - } - - @Override - public String toString() { - return name; - } - - public String getName() { - return name; - } - - public void setName(String name) { - if (StringUtil.hasText(name)) { - this.name = name; - } - } - - public String getAet() { - return calledNode.getAet(); - } - - public String getHostname() { - return calledNode.getHostname(); - } - - public Integer getPort() { - return calledNode.getPort(); - } - - public DicomNode getCalledNode() { - return calledNode; - } - - public void setCalledNode(DicomNode calledNode) { - if (calledNode != null) { - this.calledNode = calledNode; - } - } + private String name; + + private DicomNode calledNode; + + public ConfigNode(String name, DicomNode calledNode) { + this.name = Objects.requireNonNull(name); + this.calledNode = Objects.requireNonNull(calledNode); + } + + @Override + public String toString() { + return name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + if (StringUtil.hasText(name)) { + this.name = name; + } + } + + public String getAet() { + return calledNode.getAet(); + } + + public String getHostname() { + return calledNode.getHostname(); + } + + public Integer getPort() { + return calledNode.getPort(); + } + + public DicomNode getCalledNode() { + return calledNode; + } + + public void setCalledNode(DicomNode calledNode) { + if (calledNode != null) { + this.calledNode = calledNode; + } + } + } diff --git a/src/main/java/org/karnak/backend/model/dicom/DicomEchoQueryData.java b/src/main/java/org/karnak/backend/model/dicom/DicomEchoQueryData.java index ae0888fae..7be196411 100644 --- a/src/main/java/org/karnak/backend/model/dicom/DicomEchoQueryData.java +++ b/src/main/java/org/karnak/backend/model/dicom/DicomEchoQueryData.java @@ -11,59 +11,64 @@ public class DicomEchoQueryData { - private static final String DEFAULT_VALUE_FOR_CALLING_AET = "DCM-TOOLS"; + private static final String DEFAULT_VALUE_FOR_CALLING_AET = "DCM-TOOLS"; - private String callingAet; - private DicomNodeList calledDicomNodeType; - private String calledAet; - private String calledHostname; - private Integer calledPort; + private String callingAet; - public DicomEchoQueryData() { - reset(); - } + private DicomNodeList calledDicomNodeType; - public String getCallingAet() { - return callingAet; - } + private String calledAet; - public void setCallingAet(String callingAeTitle) { - this.callingAet = callingAeTitle; - } + private String calledHostname; - public DicomNodeList getCalledDicomNodeType() { - return calledDicomNodeType; - } + private Integer calledPort; - public void setCalledDicomNodeType(DicomNodeList calledDicomNodeType) { - this.calledDicomNodeType = calledDicomNodeType; - } + public DicomEchoQueryData() { + reset(); + } - public String getCalledAet() { - return calledAet; - } + public String getCallingAet() { + return callingAet; + } - public void setCalledAet(String calledAet) { - this.calledAet = calledAet; - } + public void setCallingAet(String callingAeTitle) { + this.callingAet = callingAeTitle; + } - public String getCalledHostname() { - return calledHostname; - } + public DicomNodeList getCalledDicomNodeType() { + return calledDicomNodeType; + } - public void setCalledHostname(String calledHostname) { - this.calledHostname = calledHostname; - } + public void setCalledDicomNodeType(DicomNodeList calledDicomNodeType) { + this.calledDicomNodeType = calledDicomNodeType; + } - public Integer getCalledPort() { - return calledPort; - } + public String getCalledAet() { + return calledAet; + } - public void setCalledPort(Integer calledPort) { - this.calledPort = calledPort; - } + public void setCalledAet(String calledAet) { + this.calledAet = calledAet; + } + + public String getCalledHostname() { + return calledHostname; + } + + public void setCalledHostname(String calledHostname) { + this.calledHostname = calledHostname; + } + + public Integer getCalledPort() { + return calledPort; + } + + public void setCalledPort(Integer calledPort) { + this.calledPort = calledPort; + } + + public void reset() { + callingAet = DEFAULT_VALUE_FOR_CALLING_AET; + } - public void reset() { - callingAet = DEFAULT_VALUE_FOR_CALLING_AET; - } } diff --git a/src/main/java/org/karnak/backend/model/dicom/DicomNodeList.java b/src/main/java/org/karnak/backend/model/dicom/DicomNodeList.java index a1aeb5433..1215b2290 100644 --- a/src/main/java/org/karnak/backend/model/dicom/DicomNodeList.java +++ b/src/main/java/org/karnak/backend/model/dicom/DicomNodeList.java @@ -14,29 +14,30 @@ public class DicomNodeList extends ArrayList { - private final String name; - - public DicomNodeList(String name) { - super(); - this.name = name; - } - - public DicomNodeList(String name, Collection c) { - super(c); - this.name = name; - } - - public DicomNodeList(String name, int initialCapacity) { - super(initialCapacity); - this.name = name; - } - - public String getName() { - return name; - } - - @Override - public String toString() { - return name; - } + private final String name; + + public DicomNodeList(String name) { + super(); + this.name = name; + } + + public DicomNodeList(String name, Collection c) { + super(c); + this.name = name; + } + + public DicomNodeList(String name, int initialCapacity) { + super(initialCapacity); + this.name = name; + } + + public String getName() { + return name; + } + + @Override + public String toString() { + return name; + } + } diff --git a/src/main/java/org/karnak/backend/model/dicom/Message.java b/src/main/java/org/karnak/backend/model/dicom/Message.java index 7748955ef..2923f7681 100644 --- a/src/main/java/org/karnak/backend/model/dicom/Message.java +++ b/src/main/java/org/karnak/backend/model/dicom/Message.java @@ -14,37 +14,40 @@ public class Message { - private MessageLevel level; - private MessageFormat format; - private String text; - - public Message(MessageLevel level, MessageFormat format, String text) { - this.level = level; - this.format = format; - this.text = text; - } - - public MessageLevel getLevel() { - return level; - } - - public void setLevel(MessageLevel level) { - this.level = level; - } - - public MessageFormat getFormat() { - return format; - } - - public void setFormat(MessageFormat format) { - this.format = format; - } - - public String getText() { - return text; - } - - public void setText(String text) { - this.text = text; - } + private MessageLevel level; + + private MessageFormat format; + + private String text; + + public Message(MessageLevel level, MessageFormat format, String text) { + this.level = level; + this.format = format; + this.text = text; + } + + public MessageLevel getLevel() { + return level; + } + + public void setLevel(MessageLevel level) { + this.level = level; + } + + public MessageFormat getFormat() { + return format; + } + + public void setFormat(MessageFormat format) { + this.format = format; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + } diff --git a/src/main/java/org/karnak/backend/model/dicom/WadoNode.java b/src/main/java/org/karnak/backend/model/dicom/WadoNode.java index 7506f2596..c975dc8fc 100644 --- a/src/main/java/org/karnak/backend/model/dicom/WadoNode.java +++ b/src/main/java/org/karnak/backend/model/dicom/WadoNode.java @@ -16,29 +16,32 @@ public class WadoNode { - private final String name; - private final URL url; - private final List tagEntities = new ArrayList(2); - - public WadoNode(String name, URL url) { - this.name = Objects.requireNonNull(name); - this.url = Objects.requireNonNull(url); - } - - @Override - public String toString() { - return name; - } - - public String getName() { - return name; - } - - public URL getUrl() { - return url; - } - - public List getTags() { - return tagEntities; - } + private final String name; + + private final URL url; + + private final List tagEntities = new ArrayList(2); + + public WadoNode(String name, URL url) { + this.name = Objects.requireNonNull(name); + this.url = Objects.requireNonNull(url); + } + + @Override + public String toString() { + return name; + } + + public String getName() { + return name; + } + + public URL getUrl() { + return url; + } + + public List getTags() { + return tagEntities; + } + } diff --git a/src/main/java/org/karnak/backend/model/dicom/WadoNodeList.java b/src/main/java/org/karnak/backend/model/dicom/WadoNodeList.java index b012d559b..e52fe6097 100644 --- a/src/main/java/org/karnak/backend/model/dicom/WadoNodeList.java +++ b/src/main/java/org/karnak/backend/model/dicom/WadoNodeList.java @@ -15,24 +15,25 @@ public class WadoNodeList extends ArrayList { - private final String name; - - public WadoNodeList(String name) { - this.name = Objects.requireNonNull(name); - } - - public WadoNodeList(String name, Collection c) { - super(c); - this.name = name; - } - - public WadoNodeList(String name, int initialCapacity) { - super(initialCapacity); - this.name = name; - } - - @Override - public String toString() { - return name; - } + private final String name; + + public WadoNodeList(String name) { + this.name = Objects.requireNonNull(name); + } + + public WadoNodeList(String name, Collection c) { + super(c); + this.name = name; + } + + public WadoNodeList(String name, int initialCapacity) { + super(initialCapacity); + this.name = name; + } + + @Override + public String toString() { + return name; + } + } diff --git a/src/main/java/org/karnak/backend/model/dicom/WorkListQueryData.java b/src/main/java/org/karnak/backend/model/dicom/WorkListQueryData.java index 8a87ea6f6..ec09c8124 100644 --- a/src/main/java/org/karnak/backend/model/dicom/WorkListQueryData.java +++ b/src/main/java/org/karnak/backend/model/dicom/WorkListQueryData.java @@ -14,124 +14,136 @@ public class WorkListQueryData { - private static final String DEFAULT_VALUE_FOR_CALLING_AET = "DCM-TOOLS"; - - private String callingAet; - private String workListAet; - private String workListHostname; - private Integer workListPort; - private String scheduledStationAet; - private Modality scheduledModality; - private String patientId; - private String admissionId; - private LocalDate scheduledFrom; - private LocalDate scheduledTo; - private String patientName; - private String accessionNumber; - - public WorkListQueryData() { - callingAet = DEFAULT_VALUE_FOR_CALLING_AET; - scheduledModality = Modality.ALL; - } - - public String getWorkListAet() { - return workListAet; - } - - public void setWorkListAet(String workListAet) { - this.workListAet = workListAet; - } - - public String getWorkListHostname() { - return workListHostname; - } - - public void setWorkListHostname(String workListHostname) { - this.workListHostname = workListHostname; - } - - public Integer getWorkListPort() { - return workListPort; - } - - public void setWorkListPort(Integer workListPort) { - this.workListPort = workListPort; - } - - public String getCallingAet() { - return callingAet; - } - - public void setCallingAet(String callingAet) { - this.callingAet = callingAet; - } - - public String getScheduledStationAet() { - return scheduledStationAet; - } - - public void setScheduledStationAet(String scheduledStationAet) { - this.scheduledStationAet = scheduledStationAet; - } - - public Modality getScheduledModality() { - return scheduledModality; - } - - public void setScheduledModality(Modality scheduledModality) { - this.scheduledModality = scheduledModality; - } - - public String getPatientId() { - return patientId; - } - - public void setPatientId(String patientId) { - this.patientId = patientId; - } - - public String getAdmissionId() { - return admissionId; - } - - public void setAdmissionId(String admissionId) { - this.admissionId = admissionId; - } - - public LocalDate getScheduledFrom() { - return scheduledFrom; - } - - public void setScheduledFrom(LocalDate scheduledFrom) { - this.scheduledFrom = scheduledFrom; - } - - public LocalDate getScheduledTo() { - return scheduledTo; - } - - public void setScheduledTo(LocalDate scheduledTo) { - this.scheduledTo = scheduledTo; - } - - public String getPatientName() { - return patientName; - } - - public void setPatientName(String patientName) { - this.patientName = patientName; - } - - public String getAccessionNumber() { - return accessionNumber; - } - - public void setAccessionNumber(String accessionNumber) { - this.accessionNumber = accessionNumber; - } - - public void reset() { - callingAet = DEFAULT_VALUE_FOR_CALLING_AET; - scheduledModality = Modality.ALL; - } + private static final String DEFAULT_VALUE_FOR_CALLING_AET = "DCM-TOOLS"; + + private String callingAet; + + private String workListAet; + + private String workListHostname; + + private Integer workListPort; + + private String scheduledStationAet; + + private Modality scheduledModality; + + private String patientId; + + private String admissionId; + + private LocalDate scheduledFrom; + + private LocalDate scheduledTo; + + private String patientName; + + private String accessionNumber; + + public WorkListQueryData() { + callingAet = DEFAULT_VALUE_FOR_CALLING_AET; + scheduledModality = Modality.ALL; + } + + public String getWorkListAet() { + return workListAet; + } + + public void setWorkListAet(String workListAet) { + this.workListAet = workListAet; + } + + public String getWorkListHostname() { + return workListHostname; + } + + public void setWorkListHostname(String workListHostname) { + this.workListHostname = workListHostname; + } + + public Integer getWorkListPort() { + return workListPort; + } + + public void setWorkListPort(Integer workListPort) { + this.workListPort = workListPort; + } + + public String getCallingAet() { + return callingAet; + } + + public void setCallingAet(String callingAet) { + this.callingAet = callingAet; + } + + public String getScheduledStationAet() { + return scheduledStationAet; + } + + public void setScheduledStationAet(String scheduledStationAet) { + this.scheduledStationAet = scheduledStationAet; + } + + public Modality getScheduledModality() { + return scheduledModality; + } + + public void setScheduledModality(Modality scheduledModality) { + this.scheduledModality = scheduledModality; + } + + public String getPatientId() { + return patientId; + } + + public void setPatientId(String patientId) { + this.patientId = patientId; + } + + public String getAdmissionId() { + return admissionId; + } + + public void setAdmissionId(String admissionId) { + this.admissionId = admissionId; + } + + public LocalDate getScheduledFrom() { + return scheduledFrom; + } + + public void setScheduledFrom(LocalDate scheduledFrom) { + this.scheduledFrom = scheduledFrom; + } + + public LocalDate getScheduledTo() { + return scheduledTo; + } + + public void setScheduledTo(LocalDate scheduledTo) { + this.scheduledTo = scheduledTo; + } + + public String getPatientName() { + return patientName; + } + + public void setPatientName(String patientName) { + this.patientName = patientName; + } + + public String getAccessionNumber() { + return accessionNumber; + } + + public void setAccessionNumber(String accessionNumber) { + this.accessionNumber = accessionNumber; + } + + public void reset() { + callingAet = DEFAULT_VALUE_FOR_CALLING_AET; + scheduledModality = Modality.ALL; + } + } diff --git a/src/main/java/org/karnak/backend/model/dicominnolitics/StandardAttributes.java b/src/main/java/org/karnak/backend/model/dicominnolitics/StandardAttributes.java index 60e4e94b7..7330d800b 100644 --- a/src/main/java/org/karnak/backend/model/dicominnolitics/StandardAttributes.java +++ b/src/main/java/org/karnak/backend/model/dicominnolitics/StandardAttributes.java @@ -17,24 +17,26 @@ import java.nio.charset.StandardCharsets; public class StandardAttributes { - private static final String ATTRIBUTES_FILENAME = "attributes.json"; - private StandardAttributes() {} + private static final String ATTRIBUTES_FILENAME = "attributes.json"; - public static jsonAttributes[] readJsonAttributes() { - URL url = StandardCIODS.class.getResource(ATTRIBUTES_FILENAME); - return read(url); - } + private StandardAttributes() { + } + + public static jsonAttributes[] readJsonAttributes() { + URL url = StandardCIODS.class.getResource(ATTRIBUTES_FILENAME); + return read(url); + } + + private static jsonAttributes[] read(URL url) { + Gson gson = new Gson(); + try { + JsonReader reader = new JsonReader(new InputStreamReader(url.openStream(), StandardCharsets.UTF_8)); + return gson.fromJson(reader, jsonAttributes[].class); + } + catch (Exception e) { + throw new JsonParseException(String.format("Cannot parse json %s correctly", ATTRIBUTES_FILENAME), e); + } + } - private static jsonAttributes[] read(URL url) { - Gson gson = new Gson(); - try { - JsonReader reader = - new JsonReader(new InputStreamReader(url.openStream(), StandardCharsets.UTF_8)); - return gson.fromJson(reader, jsonAttributes[].class); - } catch (Exception e) { - throw new JsonParseException( - String.format("Cannot parse json %s correctly", ATTRIBUTES_FILENAME), e); - } - } } diff --git a/src/main/java/org/karnak/backend/model/dicominnolitics/StandardCIODS.java b/src/main/java/org/karnak/backend/model/dicominnolitics/StandardCIODS.java index 6458ad0eb..156df0e1a 100644 --- a/src/main/java/org/karnak/backend/model/dicominnolitics/StandardCIODS.java +++ b/src/main/java/org/karnak/backend/model/dicominnolitics/StandardCIODS.java @@ -18,32 +18,33 @@ public class StandardCIODS { - private static final String ciodsFileName = "ciods.json"; - private static jsonCIOD[] ciods; - - public StandardCIODS() { - URL url = this.getClass().getResource(ciodsFileName); - ciods = read(url); - } - - public static jsonCIOD[] readJsonCIODS() { - URL url = StandardCIODS.class.getResource(ciodsFileName); - return read(url); - } - - private static jsonCIOD[] read(URL url) { - Gson gson = new Gson(); - try { - JsonReader reader = - new JsonReader(new InputStreamReader(url.openStream(), StandardCharsets.UTF_8)); - return gson.fromJson(reader, jsonCIOD[].class); - } catch (Exception e) { - throw new JsonParseException( - String.format("Cannot parse json %s correctly", ciodsFileName), e); - } - } - - public jsonCIOD[] getCIODS() { - return ciods; - } + private static final String ciodsFileName = "ciods.json"; + + private static jsonCIOD[] ciods; + + public StandardCIODS() { + URL url = this.getClass().getResource(ciodsFileName); + ciods = read(url); + } + + public static jsonCIOD[] readJsonCIODS() { + URL url = StandardCIODS.class.getResource(ciodsFileName); + return read(url); + } + + private static jsonCIOD[] read(URL url) { + Gson gson = new Gson(); + try { + JsonReader reader = new JsonReader(new InputStreamReader(url.openStream(), StandardCharsets.UTF_8)); + return gson.fromJson(reader, jsonCIOD[].class); + } + catch (Exception e) { + throw new JsonParseException(String.format("Cannot parse json %s correctly", ciodsFileName), e); + } + } + + public jsonCIOD[] getCIODS() { + return ciods; + } + } diff --git a/src/main/java/org/karnak/backend/model/dicominnolitics/StandardCIODtoModules.java b/src/main/java/org/karnak/backend/model/dicominnolitics/StandardCIODtoModules.java index 89e9c9872..866cc4e3a 100644 --- a/src/main/java/org/karnak/backend/model/dicominnolitics/StandardCIODtoModules.java +++ b/src/main/java/org/karnak/backend/model/dicominnolitics/StandardCIODtoModules.java @@ -18,32 +18,33 @@ public class StandardCIODtoModules { - private static final String ciodToModulesFileName = "ciod_to_modules.json"; - private static jsonCIODtoModule[] ciodToModules; - - public StandardCIODtoModules() { - URL url = this.getClass().getResource(ciodToModulesFileName); - ciodToModules = read(url); - } - - public static jsonCIODtoModule[] readJsonCIODToModules() { - URL url = StandardCIODtoModules.class.getResource(ciodToModulesFileName); - return read(url); - } - - private static jsonCIODtoModule[] read(URL url) { - Gson gson = new Gson(); - try { - JsonReader reader = - new JsonReader(new InputStreamReader(url.openStream(), StandardCharsets.UTF_8)); - return gson.fromJson(reader, jsonCIODtoModule[].class); - } catch (Exception e) { - throw new JsonParseException( - String.format("Cannot parse json %s correctly", ciodToModulesFileName), e); - } - } - - public jsonCIODtoModule[] getCIODToModules() { - return ciodToModules; - } + private static final String ciodToModulesFileName = "ciod_to_modules.json"; + + private static jsonCIODtoModule[] ciodToModules; + + public StandardCIODtoModules() { + URL url = this.getClass().getResource(ciodToModulesFileName); + ciodToModules = read(url); + } + + public static jsonCIODtoModule[] readJsonCIODToModules() { + URL url = StandardCIODtoModules.class.getResource(ciodToModulesFileName); + return read(url); + } + + private static jsonCIODtoModule[] read(URL url) { + Gson gson = new Gson(); + try { + JsonReader reader = new JsonReader(new InputStreamReader(url.openStream(), StandardCharsets.UTF_8)); + return gson.fromJson(reader, jsonCIODtoModule[].class); + } + catch (Exception e) { + throw new JsonParseException(String.format("Cannot parse json %s correctly", ciodToModulesFileName), e); + } + } + + public jsonCIODtoModule[] getCIODToModules() { + return ciodToModules; + } + } diff --git a/src/main/java/org/karnak/backend/model/dicominnolitics/StandardConfidentialityProfiles.java b/src/main/java/org/karnak/backend/model/dicominnolitics/StandardConfidentialityProfiles.java index 1eaaf117f..9c4af08e9 100644 --- a/src/main/java/org/karnak/backend/model/dicominnolitics/StandardConfidentialityProfiles.java +++ b/src/main/java/org/karnak/backend/model/dicominnolitics/StandardConfidentialityProfiles.java @@ -18,24 +18,25 @@ public class StandardConfidentialityProfiles { - private static final String confidentialityProfilesFileName = - "confidentiality_profile_attributes.json"; - private static jsonConfidentialityProfiles[] confidentialityProfiles; + private static final String confidentialityProfilesFileName = "confidentiality_profile_attributes.json"; - public StandardConfidentialityProfiles() { - URL url = this.getClass().getResource(confidentialityProfilesFileName); - Gson gson = new Gson(); - try { - JsonReader reader = - new JsonReader(new InputStreamReader(url.openStream(), StandardCharsets.UTF_8)); - confidentialityProfiles = gson.fromJson(reader, jsonConfidentialityProfiles[].class); - } catch (Exception e) { - throw new JsonParseException( - String.format("Cannot parse json %s correctly", confidentialityProfilesFileName), e); - } - } + private static jsonConfidentialityProfiles[] confidentialityProfiles; + + public StandardConfidentialityProfiles() { + URL url = this.getClass().getResource(confidentialityProfilesFileName); + Gson gson = new Gson(); + try { + JsonReader reader = new JsonReader(new InputStreamReader(url.openStream(), StandardCharsets.UTF_8)); + confidentialityProfiles = gson.fromJson(reader, jsonConfidentialityProfiles[].class); + } + catch (Exception e) { + throw new JsonParseException( + String.format("Cannot parse json %s correctly", confidentialityProfilesFileName), e); + } + } + + public static jsonConfidentialityProfiles[] getConfidentialityProfiles() { + return confidentialityProfiles; + } - public static jsonConfidentialityProfiles[] getConfidentialityProfiles() { - return confidentialityProfiles; - } } diff --git a/src/main/java/org/karnak/backend/model/dicominnolitics/StandardModuleToAttributes.java b/src/main/java/org/karnak/backend/model/dicominnolitics/StandardModuleToAttributes.java index e2116ca7f..6d64a3475 100644 --- a/src/main/java/org/karnak/backend/model/dicominnolitics/StandardModuleToAttributes.java +++ b/src/main/java/org/karnak/backend/model/dicominnolitics/StandardModuleToAttributes.java @@ -18,32 +18,34 @@ public class StandardModuleToAttributes { - private static final String moduleToAttributesFileName = "module_to_attributes.json"; - private static jsonModuleToAttribute[] moduleToAttributes; - - public StandardModuleToAttributes() { - URL url = this.getClass().getResource(moduleToAttributesFileName); - moduleToAttributes = read(url); - } - - public static jsonModuleToAttribute[] readJsonModuleToAttributes() { - URL url = StandardModuleToAttributes.class.getResource(moduleToAttributesFileName); - return read(url); - } - - private static jsonModuleToAttribute[] read(URL url) { - Gson gson = new Gson(); - try { - JsonReader reader = - new JsonReader(new InputStreamReader(url.openStream(), StandardCharsets.UTF_8)); - return gson.fromJson(reader, jsonModuleToAttribute[].class); - } catch (Exception e) { - throw new JsonParseException( - String.format("Cannot parse json %s correctly", moduleToAttributesFileName), e); - } - } - - public jsonModuleToAttribute[] getModuleToAttributes() { - return moduleToAttributes; - } + private static final String moduleToAttributesFileName = "module_to_attributes.json"; + + private static jsonModuleToAttribute[] moduleToAttributes; + + public StandardModuleToAttributes() { + URL url = this.getClass().getResource(moduleToAttributesFileName); + moduleToAttributes = read(url); + } + + public static jsonModuleToAttribute[] readJsonModuleToAttributes() { + URL url = StandardModuleToAttributes.class.getResource(moduleToAttributesFileName); + return read(url); + } + + private static jsonModuleToAttribute[] read(URL url) { + Gson gson = new Gson(); + try { + JsonReader reader = new JsonReader(new InputStreamReader(url.openStream(), StandardCharsets.UTF_8)); + return gson.fromJson(reader, jsonModuleToAttribute[].class); + } + catch (Exception e) { + throw new JsonParseException(String.format("Cannot parse json %s correctly", moduleToAttributesFileName), + e); + } + } + + public jsonModuleToAttribute[] getModuleToAttributes() { + return moduleToAttributes; + } + } diff --git a/src/main/java/org/karnak/backend/model/dicominnolitics/StandardSOPS.java b/src/main/java/org/karnak/backend/model/dicominnolitics/StandardSOPS.java index a39bd4764..011f5ba49 100644 --- a/src/main/java/org/karnak/backend/model/dicominnolitics/StandardSOPS.java +++ b/src/main/java/org/karnak/backend/model/dicominnolitics/StandardSOPS.java @@ -18,32 +18,33 @@ public class StandardSOPS { - private static final String sopsFileName = "sops.json"; - private static jsonSOP[] sops; - - public StandardSOPS() { - URL url = this.getClass().getResource(sopsFileName); - sops = read(url); - } - - public static jsonSOP[] readJsonSOPS() { - URL url = StandardSOPS.class.getResource(sopsFileName); - return read(url); - } - - private static jsonSOP[] read(URL url) { - Gson gson = new Gson(); - try { - JsonReader reader = - new JsonReader(new InputStreamReader(url.openStream(), StandardCharsets.UTF_8)); - return gson.fromJson(reader, jsonSOP[].class); - } catch (Exception e) { - throw new JsonParseException( - String.format("Cannot parse json %s correctly", sopsFileName), e); - } - } - - public jsonSOP[] getSOPS() { - return sops; - } + private static final String sopsFileName = "sops.json"; + + private static jsonSOP[] sops; + + public StandardSOPS() { + URL url = this.getClass().getResource(sopsFileName); + sops = read(url); + } + + public static jsonSOP[] readJsonSOPS() { + URL url = StandardSOPS.class.getResource(sopsFileName); + return read(url); + } + + private static jsonSOP[] read(URL url) { + Gson gson = new Gson(); + try { + JsonReader reader = new JsonReader(new InputStreamReader(url.openStream(), StandardCharsets.UTF_8)); + return gson.fromJson(reader, jsonSOP[].class); + } + catch (Exception e) { + throw new JsonParseException(String.format("Cannot parse json %s correctly", sopsFileName), e); + } + } + + public jsonSOP[] getSOPS() { + return sops; + } + } diff --git a/src/main/java/org/karnak/backend/model/dicominnolitics/jsonAttributes.java b/src/main/java/org/karnak/backend/model/dicominnolitics/jsonAttributes.java index 7261bec59..a308e0141 100644 --- a/src/main/java/org/karnak/backend/model/dicominnolitics/jsonAttributes.java +++ b/src/main/java/org/karnak/backend/model/dicominnolitics/jsonAttributes.java @@ -10,39 +10,47 @@ package org.karnak.backend.model.dicominnolitics; public class jsonAttributes { - private String tag; - private String name; - private String keyword; - private String valueRepresentation; - private String valueMultiplicity; - private String retired; - private String id; - - public String getTag() { - return tag; - } - - public String getName() { - return name; - } - - public String getKeyword() { - return keyword; - } - - public String getValueRepresentation() { - return valueRepresentation; - } - - public String getValueMultiplicity() { - return valueMultiplicity; - } - - public String getRetired() { - return retired; - } - - public String getId() { - return id; - } + + private String tag; + + private String name; + + private String keyword; + + private String valueRepresentation; + + private String valueMultiplicity; + + private String retired; + + private String id; + + public String getTag() { + return tag; + } + + public String getName() { + return name; + } + + public String getKeyword() { + return keyword; + } + + public String getValueRepresentation() { + return valueRepresentation; + } + + public String getValueMultiplicity() { + return valueMultiplicity; + } + + public String getRetired() { + return retired; + } + + public String getId() { + return id; + } + } diff --git a/src/main/java/org/karnak/backend/model/dicominnolitics/jsonCIOD.java b/src/main/java/org/karnak/backend/model/dicominnolitics/jsonCIOD.java index ba51cb9ca..5d56091e8 100644 --- a/src/main/java/org/karnak/backend/model/dicominnolitics/jsonCIOD.java +++ b/src/main/java/org/karnak/backend/model/dicominnolitics/jsonCIOD.java @@ -11,24 +11,28 @@ public class jsonCIOD { - private String name; - private String id; - private String description; - private String linkToStandard; - - public String getName() { - return name; - } - - public String getId() { - return id; - } - - public String getDescription() { - return description; - } - - public String getLinkToStandard() { - return linkToStandard; - } + private String name; + + private String id; + + private String description; + + private String linkToStandard; + + public String getName() { + return name; + } + + public String getId() { + return id; + } + + public String getDescription() { + return description; + } + + public String getLinkToStandard() { + return linkToStandard; + } + } diff --git a/src/main/java/org/karnak/backend/model/dicominnolitics/jsonCIODtoModule.java b/src/main/java/org/karnak/backend/model/dicominnolitics/jsonCIODtoModule.java index d0ad9dea9..038cac4c2 100644 --- a/src/main/java/org/karnak/backend/model/dicominnolitics/jsonCIODtoModule.java +++ b/src/main/java/org/karnak/backend/model/dicominnolitics/jsonCIODtoModule.java @@ -11,29 +11,34 @@ public class jsonCIODtoModule { - private String ciodId; - private String moduleId; - private String usage; - private String conditionalStatement; - private String informationEntity; - - public String getCiodId() { - return ciodId; - } - - public String getModuleId() { - return moduleId; - } - - public String getUsage() { - return usage; - } - - public String getConditionalStatement() { - return conditionalStatement; - } - - public String getInformationEntity() { - return informationEntity; - } + private String ciodId; + + private String moduleId; + + private String usage; + + private String conditionalStatement; + + private String informationEntity; + + public String getCiodId() { + return ciodId; + } + + public String getModuleId() { + return moduleId; + } + + public String getUsage() { + return usage; + } + + public String getConditionalStatement() { + return conditionalStatement; + } + + public String getInformationEntity() { + return informationEntity; + } + } diff --git a/src/main/java/org/karnak/backend/model/dicominnolitics/jsonConfidentialityProfiles.java b/src/main/java/org/karnak/backend/model/dicominnolitics/jsonConfidentialityProfiles.java index ecf5303e0..a49e47ef8 100644 --- a/src/main/java/org/karnak/backend/model/dicominnolitics/jsonConfidentialityProfiles.java +++ b/src/main/java/org/karnak/backend/model/dicominnolitics/jsonConfidentialityProfiles.java @@ -19,46 +19,53 @@ import org.karnak.backend.model.action.UID; public class jsonConfidentialityProfiles { - private String id; - private String name; - private String tag; - private String basicProfile; - private String stdCompIOD; - private String cleanDescOpt; - - public String getId() { - return id; - } - - public String getName() { - return name; - } - - public String getTag() { - return tag; - } - - public ActionItem getBasicProfile() { - return convertAction(basicProfile); - } - - public ActionItem getStdCompIOD() { - return convertAction(stdCompIOD); - } - - public ActionItem getCleanDescOpt() { - return convertAction(cleanDescOpt); - } - - private static ActionItem convertAction(String strAction) { - return switch (strAction) { - case "D" -> new DefaultDummy("DDum"); - case "Z" -> new ReplaceNull("Z"); - case "X" -> new Remove("X"); - case "K" -> new Keep("K"); - case "U" -> new UID("U"); - case "Z/D", "X/D", "X/Z/D", "X/Z", "X/Z/U", "X/Z/U*" -> new MultipleActions(strAction); - default -> new Replace("D"); - }; - } + + private String id; + + private String name; + + private String tag; + + private String basicProfile; + + private String stdCompIOD; + + private String cleanDescOpt; + + public String getId() { + return id; + } + + public String getName() { + return name; + } + + public String getTag() { + return tag; + } + + public ActionItem getBasicProfile() { + return convertAction(basicProfile); + } + + public ActionItem getStdCompIOD() { + return convertAction(stdCompIOD); + } + + public ActionItem getCleanDescOpt() { + return convertAction(cleanDescOpt); + } + + private static ActionItem convertAction(String strAction) { + return switch (strAction) { + case "D" -> new DefaultDummy("DDum"); + case "Z" -> new ReplaceNull("Z"); + case "X" -> new Remove("X"); + case "K" -> new Keep("K"); + case "U" -> new UID("U"); + case "Z/D", "X/D", "X/Z/D", "X/Z", "X/Z/U", "X/Z/U*" -> new MultipleActions(strAction); + default -> new Replace("D"); + }; + } + } diff --git a/src/main/java/org/karnak/backend/model/dicominnolitics/jsonModuleToAttribute.java b/src/main/java/org/karnak/backend/model/dicominnolitics/jsonModuleToAttribute.java index f872ec90c..a5f614184 100644 --- a/src/main/java/org/karnak/backend/model/dicominnolitics/jsonModuleToAttribute.java +++ b/src/main/java/org/karnak/backend/model/dicominnolitics/jsonModuleToAttribute.java @@ -11,34 +11,40 @@ public class jsonModuleToAttribute { - private String moduleId; - private String path; - private String tag; - private String type; - private String linkToStandard; - private String description; - - public String getModuleId() { - return moduleId; - } - - public String getPath() { - return path; - } - - public String getTag() { - return tag; - } - - public String getType() { - return type; - } - - public String getLinkToStandard() { - return linkToStandard; - } - - public String getDescription() { - return description; - } + private String moduleId; + + private String path; + + private String tag; + + private String type; + + private String linkToStandard; + + private String description; + + public String getModuleId() { + return moduleId; + } + + public String getPath() { + return path; + } + + public String getTag() { + return tag; + } + + public String getType() { + return type; + } + + public String getLinkToStandard() { + return linkToStandard; + } + + public String getDescription() { + return description; + } + } diff --git a/src/main/java/org/karnak/backend/model/dicominnolitics/jsonSOP.java b/src/main/java/org/karnak/backend/model/dicominnolitics/jsonSOP.java index ebcae0165..8d69c9e8a 100644 --- a/src/main/java/org/karnak/backend/model/dicominnolitics/jsonSOP.java +++ b/src/main/java/org/karnak/backend/model/dicominnolitics/jsonSOP.java @@ -11,19 +11,22 @@ public class jsonSOP { - private String name; - private String id; - private String ciod; + private String name; - public String getName() { - return name; - } + private String id; - public String getId() { - return id; - } + private String ciod; + + public String getName() { + return name; + } + + public String getId() { + return id; + } + + public String getCiod() { + return ciod; + } - public String getCiod() { - return ciod; - } } diff --git a/src/main/java/org/karnak/backend/model/echo/DestinationEcho.java b/src/main/java/org/karnak/backend/model/echo/DestinationEcho.java index 85194c1fb..afc657d5d 100644 --- a/src/main/java/org/karnak/backend/model/echo/DestinationEcho.java +++ b/src/main/java/org/karnak/backend/model/echo/DestinationEcho.java @@ -16,69 +16,70 @@ @JsonInclude(JsonInclude.Include.NON_NULL) public class DestinationEcho { - // AeTitle of the destination dicom - private String aet; - // Url of the destination stow - private String url; - // Status - private int status; - - /** Constructor without parameter */ - public DestinationEcho() {} - - /** - * Constructor with parameters - * - * @param aet AeTitle - * @param url Url - * @param status Status - */ - public DestinationEcho(String aet, String url, int status) { - this.aet = aet; - this.url = url; - this.status = status; - } - - public String getAet() { - return aet; - } - - public void setAet(String aet) { - this.aet = aet; - } - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - public int getStatus() { - return status; - } - - public void setStatus(int status) { - this.status = status; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - DestinationEcho that = (DestinationEcho) o; - return Objects.equals(aet, that.aet) - && Objects.equals(url, that.url) - && Objects.equals(status, that.status); - } - - @Override - public int hashCode() { - return Objects.hash(aet, url, status); - } + // AeTitle of the destination dicom + private String aet; + + // Url of the destination stow + private String url; + + // Status + private int status; + + /** Constructor without parameter */ + public DestinationEcho() { + } + + /** + * Constructor with parameters + * @param aet AeTitle + * @param url Url + * @param status Status + */ + public DestinationEcho(String aet, String url, int status) { + this.aet = aet; + this.url = url; + this.status = status; + } + + public String getAet() { + return aet; + } + + public void setAet(String aet) { + this.aet = aet; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public int getStatus() { + return status; + } + + public void setStatus(int status) { + this.status = status; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + DestinationEcho that = (DestinationEcho) o; + return Objects.equals(aet, that.aet) && Objects.equals(url, that.url) && Objects.equals(status, that.status); + } + + @Override + public int hashCode() { + return Objects.hash(aet, url, status); + } + } diff --git a/src/main/java/org/karnak/backend/model/echo/DestinationEchos.java b/src/main/java/org/karnak/backend/model/echo/DestinationEchos.java index 0c0d40a87..19bb9d301 100644 --- a/src/main/java/org/karnak/backend/model/echo/DestinationEchos.java +++ b/src/main/java/org/karnak/backend/model/echo/DestinationEchos.java @@ -17,15 +17,16 @@ @JacksonXmlRootElement(localName = "destinations") public class DestinationEchos { - private final List destinationEchos; + private final List destinationEchos; - public DestinationEchos(List destinationEchos) { - this.destinationEchos = destinationEchos; - } + public DestinationEchos(List destinationEchos) { + this.destinationEchos = destinationEchos; + } + + @JacksonXmlProperty(localName = "destination") + @JacksonXmlElementWrapper(useWrapping = false) + public List getDestinationEchos() { + return destinationEchos; + } - @JacksonXmlProperty(localName = "destination") - @JacksonXmlElementWrapper(useWrapping = false) - public List getDestinationEchos() { - return destinationEchos; - } } diff --git a/src/main/java/org/karnak/backend/model/editor/ConditionEditor.java b/src/main/java/org/karnak/backend/model/editor/ConditionEditor.java index 8c616832d..ca7d9ef04 100644 --- a/src/main/java/org/karnak/backend/model/editor/ConditionEditor.java +++ b/src/main/java/org/karnak/backend/model/editor/ConditionEditor.java @@ -17,21 +17,23 @@ import org.weasis.dicom.param.AttributeEditorContext.Abort; public class ConditionEditor implements AttributeEditor { - private String condition; - public ConditionEditor(String condition) { - this.condition = condition; - } + private final String condition; - private static boolean validateCondition(String condition, Attributes dcm) { - return (Boolean) ExpressionResult.get(condition, new ExprCondition(dcm), Boolean.class); - } + public ConditionEditor(String condition) { + this.condition = condition; + } + + private static boolean validateCondition(String condition, Attributes dcm) { + return (Boolean) ExpressionResult.get(condition, new ExprCondition(dcm), Boolean.class); + } + + @Override + public void apply(Attributes dcm, AttributeEditorContext context) { + if (!validateCondition(this.condition, dcm)) { + context.setAbort(Abort.FILE_EXCEPTION); + context.setAbortMessage("The instance is blocked because is does not meet the condition"); + } + } - @Override - public void apply(Attributes dcm, AttributeEditorContext context) { - if (!validateCondition(this.condition, dcm)) { - context.setAbort(Abort.FILE_EXCEPTION); - context.setAbortMessage("The instance is blocked because is does not meet the condition"); - } - } } diff --git a/src/main/java/org/karnak/backend/model/editor/DeIdentifyEditor.java b/src/main/java/org/karnak/backend/model/editor/DeIdentifyEditor.java index 8bf1a4558..29b3a69c9 100644 --- a/src/main/java/org/karnak/backend/model/editor/DeIdentifyEditor.java +++ b/src/main/java/org/karnak/backend/model/editor/DeIdentifyEditor.java @@ -19,20 +19,23 @@ public class DeIdentifyEditor implements AttributeEditor { - private final Profile profile; - private DestinationEntity destinationEntity; - private ProfileEntity profileEntity; - - public DeIdentifyEditor(DestinationEntity destinationEntity) { - this.destinationEntity = destinationEntity; - this.profileEntity = destinationEntity.getProjectEntity().getProfileEntity(); - this.profile = new Profile(profileEntity); - } - - @Override - public void apply(Attributes dcm, AttributeEditorContext context) { - if (context.getAbort() != Abort.FILE_EXCEPTION) { - profile.apply(dcm, destinationEntity, profileEntity, context); - } - } + private final Profile profile; + + private final DestinationEntity destinationEntity; + + private final ProfileEntity profileEntity; + + public DeIdentifyEditor(DestinationEntity destinationEntity) { + this.destinationEntity = destinationEntity; + this.profileEntity = destinationEntity.getProjectEntity().getProfileEntity(); + this.profile = new Profile(profileEntity); + } + + @Override + public void apply(Attributes dcm, AttributeEditorContext context) { + if (context.getAbort() != Abort.FILE_EXCEPTION) { + profile.apply(dcm, destinationEntity, profileEntity, context); + } + } + } diff --git a/src/main/java/org/karnak/backend/model/editor/FilterEditor.java b/src/main/java/org/karnak/backend/model/editor/FilterEditor.java index a26749e2e..eca1e4216 100644 --- a/src/main/java/org/karnak/backend/model/editor/FilterEditor.java +++ b/src/main/java/org/karnak/backend/model/editor/FilterEditor.java @@ -20,24 +20,21 @@ public class FilterEditor implements AttributeEditor { - private Set sopClassUIDEntitySet; + private final Set sopClassUIDEntitySet; - public FilterEditor(Set sopClassUIDEntitySet) { - this.sopClassUIDEntitySet = sopClassUIDEntitySet; - } + public FilterEditor(Set sopClassUIDEntitySet) { + this.sopClassUIDEntitySet = sopClassUIDEntitySet; + } + + @Override + public void apply(Attributes dcm, AttributeEditorContext context) { + String classUID = dcm.getString(Tag.SOPClassUID); + Predicate sopClassUIDPredicate = sopClassUID -> sopClassUID.getUid().equals(classUID); + if (sopClassUIDEntitySet.stream().noneMatch(sopClassUIDPredicate)) { + context.setAbort(Abort.FILE_EXCEPTION); + context.setAbortMessage(dcm.getString(Tag.SOPInstanceUID) + " is blocked because " + classUID + + " is not in the SOPClassUID filter"); + } + } - @Override - public void apply(Attributes dcm, AttributeEditorContext context) { - String classUID = dcm.getString(Tag.SOPClassUID); - Predicate sopClassUIDPredicate = - sopClassUID -> sopClassUID.getUid().equals(classUID); - if (sopClassUIDEntitySet.stream().noneMatch(sopClassUIDPredicate)) { - context.setAbort(Abort.FILE_EXCEPTION); - context.setAbortMessage( - dcm.getString(Tag.SOPInstanceUID) - + " is blocked because " - + classUID - + " is not in the SOPClassUID filter"); - } - } } diff --git a/src/main/java/org/karnak/backend/model/editor/StreamRegistryEditor.java b/src/main/java/org/karnak/backend/model/editor/StreamRegistryEditor.java index d211f84a5..7b0f847d7 100644 --- a/src/main/java/org/karnak/backend/model/editor/StreamRegistryEditor.java +++ b/src/main/java/org/karnak/backend/model/editor/StreamRegistryEditor.java @@ -33,104 +33,108 @@ public class StreamRegistryEditor implements AttributeEditor { - private static final Logger LOGGER = LoggerFactory.getLogger(StreamRegistryEditor.class); - private final Map studyMap = new HashMap<>(); - private boolean enable = false; - - public StreamRegistryEditor() {} - - private static LocalDateTime getDateTime(Attributes dicom, int date, int time) { - LocalDate d = DateUtil.getDicomDate(dicom.getString(date)); - LocalTime t = DateUtil.getDicomTime(dicom.getString(time)); - return DateTimeUtils.dateTime(d, t); - } - - @Override - public void apply(Attributes dcm, AttributeEditorContext context) { - if (enable) { - String studyUID = dcm.getString(Tag.StudyInstanceUID); - Study study = getStudy(studyUID); - if (study == null) { - study = new Study(studyUID, dcm.getString(Tag.PatientID)); - study.setOtherPatientIDs(dcm.getStrings(Tag.OtherPatientIDs)); - study.setAccessionNumber(dcm.getString(Tag.AccessionNumber)); - study.setStudyDescription(dcm.getString(Tag.StudyDescription, "")); - study.setStudyDate(getDateTime(dcm, Tag.StudyDate, Tag.StudyTime)); - addStudy(study); - } - - String seriesUID = dcm.getString(Tag.SeriesInstanceUID); - Series series = study.getSeries(seriesUID); - if (series == null) { - series = new Series(seriesUID); - series.setSeriesDescription( - dcm.getString(Tag.SeriesDescription, study.getStudyDescription())); - LocalDateTime dateTime = getDateTime(dcm, Tag.SeriesDate, Tag.SeriesTime); - series.setSeriesDate(dateTime == null ? study.getStudyDate() : dateTime); - study.addSeries(series); - } - - String sopUID = dcm.getString(Tag.SOPInstanceUID); - SopInstance sopInstance = series.getSopInstance(sopUID); - if (sopInstance == null) { - sopInstance = new SopInstance(sopUID); - sopInstance.setSopClassUID(dcm.getString(Tag.SOPClassUID)); - series.addSopInstance(sopInstance); - } else { - context.setAbort(Abort.FILE_EXCEPTION); - context.setAbortMessage("Duplicate transfer of " + sopUID); - } - // When it is a duplicate, avoid to send again a partial exam. - study.setTimeStamp(System.currentTimeMillis()); - } - } - - public void addStudy(Study study) { - if (study != null) { - studyMap.put(study.getStudyInstanceUID(), study); - } - } - - public Study removeStudy(String studyUID) { - return studyMap.remove(studyUID); - } - - public Study getStudy(String studyUID) { - return studyMap.get(studyUID); - } - - public Set> getEntrySet() { - return studyMap.entrySet(); - } - - public boolean isEnable() { - return enable; - } - - public void setEnable(boolean enable) { - this.enable = enable; - } - - public void update(DicomProgress progress) { - if (enable) { - Attributes dcm = progress.getAttributes(); - if (dcm != null) { - String sopUID = dcm.getString(Tag.AffectedSOPInstanceUID); - Iterator> studyIt = studyMap.entrySet().iterator(); - while (studyIt.hasNext()) { - Study study = studyIt.next().getValue(); - Iterator> seriesIt = study.getEntrySet().iterator(); - while (seriesIt.hasNext()) { - Series series = seriesIt.next().getValue(); - SopInstance sopInstance = series.getSopInstance(sopUID); - if (sopInstance != null) { - sopInstance.setSent(!progress.isLastFailed()); - return; - } - } - } - LOGGER.error("sopUID [{}] doesn't exist for notify the state", sopUID); - } - } - } + private static final Logger LOGGER = LoggerFactory.getLogger(StreamRegistryEditor.class); + + private final Map studyMap = new HashMap<>(); + + private boolean enable = false; + + public StreamRegistryEditor() { + } + + private static LocalDateTime getDateTime(Attributes dicom, int date, int time) { + LocalDate d = DateUtil.getDicomDate(dicom.getString(date)); + LocalTime t = DateUtil.getDicomTime(dicom.getString(time)); + return DateTimeUtils.dateTime(d, t); + } + + @Override + public void apply(Attributes dcm, AttributeEditorContext context) { + if (enable) { + String studyUID = dcm.getString(Tag.StudyInstanceUID); + Study study = getStudy(studyUID); + if (study == null) { + study = new Study(studyUID, dcm.getString(Tag.PatientID)); + study.setOtherPatientIDs(dcm.getStrings(Tag.OtherPatientIDs)); + study.setAccessionNumber(dcm.getString(Tag.AccessionNumber)); + study.setStudyDescription(dcm.getString(Tag.StudyDescription, "")); + study.setStudyDate(getDateTime(dcm, Tag.StudyDate, Tag.StudyTime)); + addStudy(study); + } + + String seriesUID = dcm.getString(Tag.SeriesInstanceUID); + Series series = study.getSeries(seriesUID); + if (series == null) { + series = new Series(seriesUID); + series.setSeriesDescription(dcm.getString(Tag.SeriesDescription, study.getStudyDescription())); + LocalDateTime dateTime = getDateTime(dcm, Tag.SeriesDate, Tag.SeriesTime); + series.setSeriesDate(dateTime == null ? study.getStudyDate() : dateTime); + study.addSeries(series); + } + + String sopUID = dcm.getString(Tag.SOPInstanceUID); + SopInstance sopInstance = series.getSopInstance(sopUID); + if (sopInstance == null) { + sopInstance = new SopInstance(sopUID); + sopInstance.setSopClassUID(dcm.getString(Tag.SOPClassUID)); + series.addSopInstance(sopInstance); + } + else { + context.setAbort(Abort.FILE_EXCEPTION); + context.setAbortMessage("Duplicate transfer of " + sopUID); + } + // When it is a duplicate, avoid to send again a partial exam. + study.setTimeStamp(System.currentTimeMillis()); + } + } + + public void addStudy(Study study) { + if (study != null) { + studyMap.put(study.getStudyInstanceUID(), study); + } + } + + public Study removeStudy(String studyUID) { + return studyMap.remove(studyUID); + } + + public Study getStudy(String studyUID) { + return studyMap.get(studyUID); + } + + public Set> getEntrySet() { + return studyMap.entrySet(); + } + + public boolean isEnable() { + return enable; + } + + public void setEnable(boolean enable) { + this.enable = enable; + } + + public void update(DicomProgress progress) { + if (enable) { + Attributes dcm = progress.getAttributes(); + if (dcm != null) { + String sopUID = dcm.getString(Tag.AffectedSOPInstanceUID); + Iterator> studyIt = studyMap.entrySet().iterator(); + while (studyIt.hasNext()) { + Study study = studyIt.next().getValue(); + Iterator> seriesIt = study.getEntrySet().iterator(); + while (seriesIt.hasNext()) { + Series series = seriesIt.next().getValue(); + SopInstance sopInstance = series.getSopInstance(sopUID); + if (sopInstance != null) { + sopInstance.setSent(!progress.isLastFailed()); + return; + } + } + } + LOGGER.error("sopUID [{}] doesn't exist for notify the state", sopUID); + } + } + } + } diff --git a/src/main/java/org/karnak/backend/model/event/NodeEvent.java b/src/main/java/org/karnak/backend/model/event/NodeEvent.java index 4d6052a84..0bfd104f7 100644 --- a/src/main/java/org/karnak/backend/model/event/NodeEvent.java +++ b/src/main/java/org/karnak/backend/model/event/NodeEvent.java @@ -17,34 +17,37 @@ import org.springframework.context.ApplicationEvent; public class NodeEvent extends ApplicationEvent { - private static final long serialVersionUID = -15504960651765311L; - - private final NodeEventType eventType; - private final ForwardNodeEntity forwardNodeEntity; - - public NodeEvent(ForwardNodeEntity fwdNode, NodeEventType eventType) { - super(fwdNode); - this.forwardNodeEntity = fwdNode; - this.eventType = eventType; - } - - public NodeEvent(DicomSourceNodeEntity srcNode, NodeEventType eventType) { - super(srcNode); - this.forwardNodeEntity = Objects.requireNonNull(srcNode.getForwardNodeEntity()); - this.eventType = eventType; - } - - public NodeEvent(DestinationEntity dstNode, NodeEventType eventType) { - super(dstNode); - this.forwardNodeEntity = Objects.requireNonNull(dstNode.getForwardNodeEntity()); - this.eventType = eventType; - } - - public ForwardNodeEntity getForwardNode() { - return forwardNodeEntity; - } - - public NodeEventType getEventType() { - return eventType; - } + + private static final long serialVersionUID = -15504960651765311L; + + private final NodeEventType eventType; + + private final ForwardNodeEntity forwardNodeEntity; + + public NodeEvent(ForwardNodeEntity fwdNode, NodeEventType eventType) { + super(fwdNode); + this.forwardNodeEntity = fwdNode; + this.eventType = eventType; + } + + public NodeEvent(DicomSourceNodeEntity srcNode, NodeEventType eventType) { + super(srcNode); + this.forwardNodeEntity = Objects.requireNonNull(srcNode.getForwardNodeEntity()); + this.eventType = eventType; + } + + public NodeEvent(DestinationEntity dstNode, NodeEventType eventType) { + super(dstNode); + this.forwardNodeEntity = Objects.requireNonNull(dstNode.getForwardNodeEntity()); + this.eventType = eventType; + } + + public ForwardNodeEntity getForwardNode() { + return forwardNodeEntity; + } + + public NodeEventType getEventType() { + return eventType; + } + } diff --git a/src/main/java/org/karnak/backend/model/event/TransferMonitoringEvent.java b/src/main/java/org/karnak/backend/model/event/TransferMonitoringEvent.java index d8ce09cf7..2e720a879 100644 --- a/src/main/java/org/karnak/backend/model/event/TransferMonitoringEvent.java +++ b/src/main/java/org/karnak/backend/model/event/TransferMonitoringEvent.java @@ -15,7 +15,8 @@ /** Transfer monitoring event used to populate asynchronously transfer_status table */ public class TransferMonitoringEvent extends ApplicationEvent { - public TransferMonitoringEvent(TransferStatusEntity transferStatusEntity) { - super(transferStatusEntity); - } + public TransferMonitoringEvent(TransferStatusEntity transferStatusEntity) { + super(transferStatusEntity); + } + } diff --git a/src/main/java/org/karnak/backend/model/expression/ExprAction.java b/src/main/java/org/karnak/backend/model/expression/ExprAction.java index 94ef6013e..d65f343b1 100644 --- a/src/main/java/org/karnak/backend/model/expression/ExprAction.java +++ b/src/main/java/org/karnak/backend/model/expression/ExprAction.java @@ -23,92 +23,97 @@ public class ExprAction implements ExpressionItem { - private int tag; - private VR vr; - private String stringValue; - private Attributes dcm; - private Attributes dcmCopy; - - public ExprAction(int tag, VR vr, Attributes dcm, Attributes dcmCopy) { - this.tag = Objects.requireNonNull(tag); - this.vr = Objects.requireNonNull(vr); - this.stringValue = dcmCopy.getString(this.tag); - this.dcmCopy = dcmCopy; - this.dcm = dcm; - } - - public ExprAction(int tag, VR vr, String stringValue) { - this.tag = Objects.requireNonNull(tag); - this.vr = Objects.requireNonNull(vr); - this.stringValue = stringValue; - } - - public static boolean isHexTag(String elem) { - String cleanElem = elem.replaceAll("[(),]", "").toUpperCase(); - - if (!StringUtil.hasText(cleanElem) || cleanElem.length() != 8) { - return false; - } - return cleanElem.matches("[0-9A-FX]+"); - } - - public int getTag() { - return tag; - } - - public void setTag(int tag) { - this.tag = tag; - } - - public VR getVr() { - return vr; - } - - public void setVr(VR vr) { - this.vr = vr; - } - - public String getStringValue() { - return stringValue; - } - - public void setStringValue(String stringValue) { - this.stringValue = stringValue; - } - - public ActionItem Keep() { - return new Keep("K"); - } - - public ActionItem Remove() { - return new Remove("X"); - } - - public ActionItem Replace(String dummyValue) { - ActionItem replace = new Replace("D"); - replace.setDummyValue(dummyValue); - return replace; - } - - public ActionItem UID() { - return new UID("U"); - } - - public ActionItem ReplaceNull() { - return new ReplaceNull("Z"); - } - - public String getString(int tag) { - return dcmCopy.getString(tag); - } - - public boolean tagIsPresent(int tag) { - return DicomObjectTools.containsTagInAllAttributes(tag, dcmCopy); - } - - /*public ActionItem Add(int newTag, VR newVr, String newValue){ - Add add = new Add("A", newTag, newVr, newValue); - add.execute(dcm, newTag, null, null); - return null; - }*/ + private int tag; + + private VR vr; + + private String stringValue; + + private Attributes dcm; + + private Attributes dcmCopy; + + public ExprAction(int tag, VR vr, Attributes dcm, Attributes dcmCopy) { + this.tag = Objects.requireNonNull(tag); + this.vr = Objects.requireNonNull(vr); + this.stringValue = dcmCopy.getString(this.tag); + this.dcmCopy = dcmCopy; + this.dcm = dcm; + } + + public ExprAction(int tag, VR vr, String stringValue) { + this.tag = Objects.requireNonNull(tag); + this.vr = Objects.requireNonNull(vr); + this.stringValue = stringValue; + } + + public static boolean isHexTag(String elem) { + String cleanElem = elem.replaceAll("[(),]", "").toUpperCase(); + + if (!StringUtil.hasText(cleanElem) || cleanElem.length() != 8) { + return false; + } + return cleanElem.matches("[0-9A-FX]+"); + } + + public int getTag() { + return tag; + } + + public void setTag(int tag) { + this.tag = tag; + } + + public VR getVr() { + return vr; + } + + public void setVr(VR vr) { + this.vr = vr; + } + + public String getStringValue() { + return stringValue; + } + + public void setStringValue(String stringValue) { + this.stringValue = stringValue; + } + + public ActionItem Keep() { + return new Keep("K"); + } + + public ActionItem Remove() { + return new Remove("X"); + } + + public ActionItem Replace(String dummyValue) { + ActionItem replace = new Replace("D"); + replace.setDummyValue(dummyValue); + return replace; + } + + public ActionItem UID() { + return new UID("U"); + } + + public ActionItem ReplaceNull() { + return new ReplaceNull("Z"); + } + + public String getString(int tag) { + return dcmCopy.getString(tag); + } + + public boolean tagIsPresent(int tag) { + return DicomObjectTools.containsTagInAllAttributes(tag, dcmCopy); + } + + /* + * public ActionItem Add(int newTag, VR newVr, String newValue){ Add add = new + * Add("A", newTag, newVr, newValue); add.execute(dcm, newTag, null, null); return + * null; } + */ + } diff --git a/src/main/java/org/karnak/backend/model/expression/ExprCondition.java b/src/main/java/org/karnak/backend/model/expression/ExprCondition.java index 7e9d55395..8c27cac19 100644 --- a/src/main/java/org/karnak/backend/model/expression/ExprCondition.java +++ b/src/main/java/org/karnak/backend/model/expression/ExprCondition.java @@ -14,78 +14,73 @@ public class ExprCondition implements ExpressionItem { - private final Attributes dcm; - - public ExprCondition() { - this(new Attributes()); - } - - public ExprCondition(Attributes dcm) { - this.dcm = dcm; - } - - public static void expressionValidation(String condition) { - ExprCondition exprCondition = new ExprCondition(); - ExpressionResult.get(condition, exprCondition, Boolean.class); - } - - public static int intFromHexString(String tag) { - String cleanTag = tag.replaceAll("[(),]", "").toUpperCase(); - return TagUtils.intFromHexString(cleanTag); - } - - public boolean tagValueIsPresent(String tag, String value) { - int cleanTag = intFromHexString(tag); - return tagValueIsPresent(cleanTag, value); - } - - public boolean tagValueIsPresent(int tag, String value) { - String dcmValue = dcm.getString(tag); - return dcmValue != null && dcmValue.equals(value); - } - - public boolean tagValueContains(String tag, String value) { - int cleanTag = intFromHexString(tag); - return tagValueContains(cleanTag, value); - } - - public boolean tagValueContains(int tag, String value) { - String dcmValue = dcm.getString(tag); - return dcmValue != null && dcmValue.contains(value); - } - - public boolean tagValueBeginsWith(String tag, String value) { - int cleanTag = intFromHexString(tag); - return tagValueBeginsWith(cleanTag, value); - } - - public boolean tagValueBeginsWith(int tag, String value) { - String dcmValue = dcm.getString(tag); - return dcmValue != null && dcmValue.startsWith(value); - } - - public boolean tagValueEndsWith(String tag, String value) { - int cleanTag = intFromHexString(tag); - return tagValueEndsWith(cleanTag, value); + private final Attributes dcm; + + public ExprCondition() { + this(new Attributes()); + } + + public ExprCondition(Attributes dcm) { + this.dcm = dcm; + } + + public static void expressionValidation(String condition) { + ExprCondition exprCondition = new ExprCondition(); + ExpressionResult.get(condition, exprCondition, Boolean.class); + } + + public static int intFromHexString(String tag) { + String cleanTag = tag.replaceAll("[(),]", "").toUpperCase(); + return TagUtils.intFromHexString(cleanTag); + } + + public boolean tagValueIsPresent(String tag, String value) { + int cleanTag = intFromHexString(tag); + return tagValueIsPresent(cleanTag, value); + } + + public boolean tagValueIsPresent(int tag, String value) { + String dcmValue = dcm.getString(tag); + return dcmValue != null && dcmValue.equals(value); + } + + public boolean tagValueContains(String tag, String value) { + int cleanTag = intFromHexString(tag); + return tagValueContains(cleanTag, value); + } + + public boolean tagValueContains(int tag, String value) { + String dcmValue = dcm.getString(tag); + return dcmValue != null && dcmValue.contains(value); + } + + public boolean tagValueBeginsWith(String tag, String value) { + int cleanTag = intFromHexString(tag); + return tagValueBeginsWith(cleanTag, value); + } + + public boolean tagValueBeginsWith(int tag, String value) { + String dcmValue = dcm.getString(tag); + return dcmValue != null && dcmValue.startsWith(value); + } + + public boolean tagValueEndsWith(String tag, String value) { + int cleanTag = intFromHexString(tag); + return tagValueEndsWith(cleanTag, value); + } + + public boolean tagValueEndsWith(int tag, String value) { + String dcmValue = dcm.getString(tag); + return dcmValue != null && dcmValue.endsWith(value); + } + + public boolean tagIsPresent(String tag) { + int cleanTag = intFromHexString(tag); + return dcm.getString(cleanTag) != null; } - public boolean tagValueEndsWith(int tag, String value) { - String dcmValue = dcm.getString(tag); - return dcmValue != null && dcmValue.endsWith(value); + public boolean tagIsPresent(int tag) { + return dcm.getString(tag) != null; } - public boolean tagIsPresent(String tag) { - int cleanTag = intFromHexString(tag); - if (dcm.getString(cleanTag) != null) { - return true; - } - return false; - } - - public boolean tagIsPresent(int tag) { - if (dcm.getString(tag) != null) { - return true; - } - return false; - } } diff --git a/src/main/java/org/karnak/backend/model/expression/ExpressionError.java b/src/main/java/org/karnak/backend/model/expression/ExpressionError.java index 8bbb11111..b7d9552a1 100644 --- a/src/main/java/org/karnak/backend/model/expression/ExpressionError.java +++ b/src/main/java/org/karnak/backend/model/expression/ExpressionError.java @@ -11,27 +11,29 @@ public class ExpressionError { - private boolean isValid; - private String msg; + private boolean isValid; - public ExpressionError(boolean isValid, String msg) { - this.isValid = isValid; - this.msg = msg; - } + private String msg; - public boolean isValid() { - return isValid; - } + public ExpressionError(boolean isValid, String msg) { + this.isValid = isValid; + this.msg = msg; + } - public void setValid(boolean valid) { - isValid = valid; - } + public boolean isValid() { + return isValid; + } - public String getMsg() { - return msg; - } + public void setValid(boolean valid) { + isValid = valid; + } + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } - public void setMsg(String msg) { - this.msg = msg; - } } diff --git a/src/main/java/org/karnak/backend/model/expression/ExpressionItem.java b/src/main/java/org/karnak/backend/model/expression/ExpressionItem.java index b1df15b64..4add8bd98 100644 --- a/src/main/java/org/karnak/backend/model/expression/ExpressionItem.java +++ b/src/main/java/org/karnak/backend/model/expression/ExpressionItem.java @@ -9,4 +9,6 @@ */ package org.karnak.backend.model.expression; -public interface ExpressionItem {} +public interface ExpressionItem { + +} diff --git a/src/main/java/org/karnak/backend/model/expression/ExpressionResult.java b/src/main/java/org/karnak/backend/model/expression/ExpressionResult.java index 8bc85bd94..a06448352 100644 --- a/src/main/java/org/karnak/backend/model/expression/ExpressionResult.java +++ b/src/main/java/org/karnak/backend/model/expression/ExpressionResult.java @@ -20,33 +20,34 @@ // https://docs.spring.io/spring/docs/3.0.x/reference/expressions.html public class ExpressionResult { - public static Object get(String condition, ExpressionItem expressionItem, Class typeOfReturn) { - try { - final ExpressionParser parser = new SpelExpressionParser(); - final EvaluationContext context = new StandardEvaluationContext(expressionItem); - context.setVariable("VR", VR.class); - context.setVariable("Tag", Tag.class); - final Expression exp = parser.parseExpression(condition); - return exp.getValue(context, typeOfReturn); - } catch (final Exception e) { - throw new IllegalStateException( - String.format("Cannot execute the parser expression for this expression: %s", condition)); - } - } + public static Object get(String condition, ExpressionItem expressionItem, Class typeOfReturn) { + try { + final ExpressionParser parser = new SpelExpressionParser(); + final EvaluationContext context = new StandardEvaluationContext(expressionItem); + context.setVariable("VR", VR.class); + context.setVariable("Tag", Tag.class); + final Expression exp = parser.parseExpression(condition); + return exp.getValue(context, typeOfReturn); + } + catch (final Exception e) { + throw new IllegalStateException( + String.format("Cannot execute the parser expression for this expression: %s", condition)); + } + } + + public static ExpressionError isValid(String condition, ExpressionItem expressionItem, Class typeOfReturn) { + try { + final ExpressionParser parser = new SpelExpressionParser(); + final EvaluationContext context = new StandardEvaluationContext(expressionItem); + context.setVariable("VR", VR.class); + context.setVariable("Tag", Tag.class); + final Expression exp = parser.parseExpression(condition); + Object o = exp.getValue(context, typeOfReturn); + return new ExpressionError(true, null); + } + catch (final Exception e) { + return new ExpressionError(false, String.format("Expression is not valid: \n\r%s", e.getMessage())); + } + } - public static ExpressionError isValid( - String condition, ExpressionItem expressionItem, Class typeOfReturn) { - try { - final ExpressionParser parser = new SpelExpressionParser(); - final EvaluationContext context = new StandardEvaluationContext(expressionItem); - context.setVariable("VR", VR.class); - context.setVariable("Tag", Tag.class); - final Expression exp = parser.parseExpression(condition); - Object o = exp.getValue(context, typeOfReturn); - return new ExpressionError(true, null); - } catch (final Exception e) { - return new ExpressionError( - false, String.format("Expression is not valid: \n\r%s", e.getMessage())); - } - } } diff --git a/src/main/java/org/karnak/backend/model/kheops/MetadataSwitching.java b/src/main/java/org/karnak/backend/model/kheops/MetadataSwitching.java index 29bcf6cdd..4f1451a2a 100644 --- a/src/main/java/org/karnak/backend/model/kheops/MetadataSwitching.java +++ b/src/main/java/org/karnak/backend/model/kheops/MetadataSwitching.java @@ -11,36 +11,39 @@ public class MetadataSwitching { - private final String studyInstanceUID; - private final String seriesInstanceUID; - private final String SOPinstanceUID; - private boolean applied; - - public MetadataSwitching( - String studyInstanceUID, String seriesInstanceUID, String SOPinstanceUID) { - this.studyInstanceUID = studyInstanceUID; - this.seriesInstanceUID = seriesInstanceUID; - this.SOPinstanceUID = SOPinstanceUID; - this.applied = false; - } - - public String getStudyInstanceUID() { - return studyInstanceUID; - } - - public String getSeriesInstanceUID() { - return seriesInstanceUID; - } - - public String getSOPinstanceUID() { - return SOPinstanceUID; - } - - public boolean isApplied() { - return applied; - } - - public void setApplied(boolean applied) { - this.applied = applied; - } + private final String studyInstanceUID; + + private final String seriesInstanceUID; + + private final String SOPinstanceUID; + + private boolean applied; + + public MetadataSwitching(String studyInstanceUID, String seriesInstanceUID, String SOPinstanceUID) { + this.studyInstanceUID = studyInstanceUID; + this.seriesInstanceUID = seriesInstanceUID; + this.SOPinstanceUID = SOPinstanceUID; + this.applied = false; + } + + public String getStudyInstanceUID() { + return studyInstanceUID; + } + + public String getSeriesInstanceUID() { + return seriesInstanceUID; + } + + public String getSOPinstanceUID() { + return SOPinstanceUID; + } + + public boolean isApplied() { + return applied; + } + + public void setApplied(boolean applied) { + this.applied = applied; + } + } diff --git a/src/main/java/org/karnak/backend/model/notification/SerieSummaryNotification.java b/src/main/java/org/karnak/backend/model/notification/SerieSummaryNotification.java index 9d9725921..7d1fedca7 100644 --- a/src/main/java/org/karnak/backend/model/notification/SerieSummaryNotification.java +++ b/src/main/java/org/karnak/backend/model/notification/SerieSummaryNotification.java @@ -17,91 +17,90 @@ /** Model used for serie summary notification */ public class SerieSummaryNotification { - private String serieUid; - private String serieDescription; - private LocalDateTime serieDate; - private long nbTransferSent; - private long nbTransferNotSent; - private List unTransferedReasons; - - public String getSerieUid() { - return serieUid; - } - - public void setSerieUid(String serieUid) { - this.serieUid = serieUid; - } - - public String getSerieDescription() { - return serieDescription; - } - - public void setSerieDescription(String serieDescription) { - this.serieDescription = serieDescription; - } - - public LocalDateTime getSerieDate() { - return serieDate; - } - - public void setSerieDate(LocalDateTime serieDate) { - this.serieDate = serieDate; - } - - public long getNbTransferSent() { - return nbTransferSent; - } - - public void setNbTransferSent(long nbTransferSent) { - this.nbTransferSent = nbTransferSent; - } - - public long getNbTransferNotSent() { - return nbTransferNotSent; - } - - public void setNbTransferNotSent(long nbTransferNotSent) { - this.nbTransferNotSent = nbTransferNotSent; - } - - public List getUnTransferedReasons() { - return unTransferedReasons; - } - - public void setUnTransferedReasons(List unTransferedReasons) { - this.unTransferedReasons = unTransferedReasons; - } - - @Override - public boolean equals(Object o) { - - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - SerieSummaryNotification that = (SerieSummaryNotification) o; - return nbTransferSent == that.nbTransferSent - && nbTransferNotSent == that.nbTransferNotSent - && Objects.equals(serieUid, that.serieUid) - && Objects.equals(serieDescription, that.serieDescription) - && Objects.equals(serieDate, that.serieDate) - && Objects.equals(unTransferedReasons, that.unTransferedReasons); - } - - @Override - public int hashCode() { - return Objects.hash( - serieUid, - serieDescription, - serieDate, - nbTransferSent, - nbTransferNotSent, - unTransferedReasons); - } - - public String toStringUnTransferredReasons() { - return String.join(Notification.COMMA_SEPARATOR, unTransferedReasons); - } + private String serieUid; + + private String serieDescription; + + private LocalDateTime serieDate; + + private long nbTransferSent; + + private long nbTransferNotSent; + + private List unTransferedReasons; + + public String getSerieUid() { + return serieUid; + } + + public void setSerieUid(String serieUid) { + this.serieUid = serieUid; + } + + public String getSerieDescription() { + return serieDescription; + } + + public void setSerieDescription(String serieDescription) { + this.serieDescription = serieDescription; + } + + public LocalDateTime getSerieDate() { + return serieDate; + } + + public void setSerieDate(LocalDateTime serieDate) { + this.serieDate = serieDate; + } + + public long getNbTransferSent() { + return nbTransferSent; + } + + public void setNbTransferSent(long nbTransferSent) { + this.nbTransferSent = nbTransferSent; + } + + public long getNbTransferNotSent() { + return nbTransferNotSent; + } + + public void setNbTransferNotSent(long nbTransferNotSent) { + this.nbTransferNotSent = nbTransferNotSent; + } + + public List getUnTransferedReasons() { + return unTransferedReasons; + } + + public void setUnTransferedReasons(List unTransferedReasons) { + this.unTransferedReasons = unTransferedReasons; + } + + @Override + public boolean equals(Object o) { + + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + SerieSummaryNotification that = (SerieSummaryNotification) o; + return nbTransferSent == that.nbTransferSent && nbTransferNotSent == that.nbTransferNotSent + && Objects.equals(serieUid, that.serieUid) && Objects.equals(serieDescription, that.serieDescription) + && Objects.equals(serieDate, that.serieDate) + && Objects.equals(unTransferedReasons, that.unTransferedReasons); + } + + @Override + public int hashCode() { + return Objects.hash(serieUid, serieDescription, serieDate, nbTransferSent, nbTransferNotSent, + unTransferedReasons); + } + + public String toStringUnTransferredReasons() { + return String.join(Notification.COMMA_SEPARATOR, unTransferedReasons); + } + } diff --git a/src/main/java/org/karnak/backend/model/notification/TransferMonitoringNotification.java b/src/main/java/org/karnak/backend/model/notification/TransferMonitoringNotification.java index 87d417e5b..3cf10f864 100644 --- a/src/main/java/org/karnak/backend/model/notification/TransferMonitoringNotification.java +++ b/src/main/java/org/karnak/backend/model/notification/TransferMonitoringNotification.java @@ -16,142 +16,137 @@ /** Model used to build transfer monitoring notification */ public class TransferMonitoringNotification { - private String subject; - private String from; - private String to; - private String patientId; - private String studyUid; - private String accessionNumber; - private String studyDescription; - private LocalDateTime studyDate; - private String source; - private String destination; - private List serieSummaryNotifications; - - public String getSubject() { - return subject; - } - - public void setSubject(String subject) { - this.subject = subject; - } - - public String getFrom() { - return from; - } - - public void setFrom(String from) { - this.from = from; - } - - public String getTo() { - return to; - } - - public void setTo(String to) { - this.to = to; - } - - public String getPatientId() { - return patientId; - } - - public void setPatientId(String patientId) { - this.patientId = patientId; - } - - public String getStudyUid() { - return studyUid; - } - - public void setStudyUid(String studyUid) { - this.studyUid = studyUid; - } - - public String getAccessionNumber() { - return accessionNumber; - } - - public void setAccessionNumber(String accessionNumber) { - this.accessionNumber = accessionNumber; - } - - public String getStudyDescription() { - return studyDescription; - } - - public void setStudyDescription(String studyDescription) { - this.studyDescription = studyDescription; - } - - public LocalDateTime getStudyDate() { - return studyDate; - } - - public void setStudyDate(LocalDateTime studyDate) { - this.studyDate = studyDate; - } - - public String getSource() { - return source; - } - - public void setSource(String source) { - this.source = source; - } - - public String getDestination() { - return destination; - } - - public void setDestination(String destination) { - this.destination = destination; - } - - public List getSerieSummaryNotifications() { - return serieSummaryNotifications; - } - - public void setSerieSummaryNotifications( - List serieSummaryNotifications) { - this.serieSummaryNotifications = serieSummaryNotifications; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - TransferMonitoringNotification that = (TransferMonitoringNotification) o; - return Objects.equals(subject, that.subject) - && Objects.equals(from, that.from) - && Objects.equals(to, that.to) - && Objects.equals(patientId, that.patientId) - && Objects.equals(studyUid, that.studyUid) - && Objects.equals(accessionNumber, that.accessionNumber) - && Objects.equals(studyDescription, that.studyDescription) - && Objects.equals(studyDate, that.studyDate) - && Objects.equals(source, that.source) - && Objects.equals(destination, that.destination) - && Objects.equals(serieSummaryNotifications, that.serieSummaryNotifications); - } - - @Override - public int hashCode() { - return Objects.hash( - subject, - from, - to, - patientId, - studyUid, - accessionNumber, - studyDescription, - studyDate, - source, - destination, - serieSummaryNotifications); - } + private String subject; + + private String from; + + private String to; + + private String patientId; + + private String studyUid; + + private String accessionNumber; + + private String studyDescription; + + private LocalDateTime studyDate; + + private String source; + + private String destination; + + private List serieSummaryNotifications; + + public String getSubject() { + return subject; + } + + public void setSubject(String subject) { + this.subject = subject; + } + + public String getFrom() { + return from; + } + + public void setFrom(String from) { + this.from = from; + } + + public String getTo() { + return to; + } + + public void setTo(String to) { + this.to = to; + } + + public String getPatientId() { + return patientId; + } + + public void setPatientId(String patientId) { + this.patientId = patientId; + } + + public String getStudyUid() { + return studyUid; + } + + public void setStudyUid(String studyUid) { + this.studyUid = studyUid; + } + + public String getAccessionNumber() { + return accessionNumber; + } + + public void setAccessionNumber(String accessionNumber) { + this.accessionNumber = accessionNumber; + } + + public String getStudyDescription() { + return studyDescription; + } + + public void setStudyDescription(String studyDescription) { + this.studyDescription = studyDescription; + } + + public LocalDateTime getStudyDate() { + return studyDate; + } + + public void setStudyDate(LocalDateTime studyDate) { + this.studyDate = studyDate; + } + + public String getSource() { + return source; + } + + public void setSource(String source) { + this.source = source; + } + + public String getDestination() { + return destination; + } + + public void setDestination(String destination) { + this.destination = destination; + } + + public List getSerieSummaryNotifications() { + return serieSummaryNotifications; + } + + public void setSerieSummaryNotifications(List serieSummaryNotifications) { + this.serieSummaryNotifications = serieSummaryNotifications; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + TransferMonitoringNotification that = (TransferMonitoringNotification) o; + return Objects.equals(subject, that.subject) && Objects.equals(from, that.from) && Objects.equals(to, that.to) + && Objects.equals(patientId, that.patientId) && Objects.equals(studyUid, that.studyUid) + && Objects.equals(accessionNumber, that.accessionNumber) + && Objects.equals(studyDescription, that.studyDescription) && Objects.equals(studyDate, that.studyDate) + && Objects.equals(source, that.source) && Objects.equals(destination, that.destination) + && Objects.equals(serieSummaryNotifications, that.serieSummaryNotifications); + } + + @Override + public int hashCode() { + return Objects.hash(subject, from, to, patientId, studyUid, accessionNumber, studyDescription, studyDate, + source, destination, serieSummaryNotifications); + } + } diff --git a/src/main/java/org/karnak/backend/model/profilebody/MaskBody.java b/src/main/java/org/karnak/backend/model/profilebody/MaskBody.java index 5f81740a0..1b1236a84 100644 --- a/src/main/java/org/karnak/backend/model/profilebody/MaskBody.java +++ b/src/main/java/org/karnak/backend/model/profilebody/MaskBody.java @@ -13,31 +13,34 @@ public class MaskBody { - private String stationName; - private String color; - private List rectangles; + private String stationName; - public String getStationName() { - return stationName; - } + private String color; - public void setStationName(String stationName) { - this.stationName = stationName; - } + private List rectangles; - public String getColor() { - return color; - } + public String getStationName() { + return stationName; + } - public void setColor(String color) { - this.color = color; - } + public void setStationName(String stationName) { + this.stationName = stationName; + } - public List getRectangles() { - return rectangles; - } + public String getColor() { + return color; + } + + public void setColor(String color) { + this.color = color; + } + + public List getRectangles() { + return rectangles; + } + + public void setRectangles(List rectangles) { + this.rectangles = rectangles; + } - public void setRectangles(List rectangles) { - this.rectangles = rectangles; - } } diff --git a/src/main/java/org/karnak/backend/model/profilebody/ProfileElementBody.java b/src/main/java/org/karnak/backend/model/profilebody/ProfileElementBody.java index 3450b3e76..7ddb31cfd 100644 --- a/src/main/java/org/karnak/backend/model/profilebody/ProfileElementBody.java +++ b/src/main/java/org/karnak/backend/model/profilebody/ProfileElementBody.java @@ -14,85 +14,94 @@ public class ProfileElementBody { - private String name; - private String codename; - private String condition; - private String action; - private String option; - private String args; - private List tagEntities; - private List excludedTags; - private Map arguments; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getCodename() { - return codename; - } - - public void setCodename(String codename) { - this.codename = codename; - } - - public String getCondition() { - return condition; - } - - public void setCondition(String condition) { - this.condition = condition; - } - - public String getAction() { - return action; - } - - public void setAction(String action) { - this.action = action; - } - - public String getOption() { - return option; - } - - public void setOption(String option) { - this.option = option; - } - - public String getArgs() { - return args; - } - - public void setArgs(String args) { - this.args = args; - } - - public Map getArguments() { - return arguments; - } - - public void setArguments(Map arguments) { - this.arguments = arguments; - } - - public List getTags() { - return tagEntities; - } - - public void setTags(List tagEntities) { - this.tagEntities = tagEntities; - } - - public List getExcludedTags() { - return excludedTags; - } - - public void setExcludedTags(List excludedTags) { - this.excludedTags = excludedTags; - } + private String name; + + private String codename; + + private String condition; + + private String action; + + private String option; + + private String args; + + private List tagEntities; + + private List excludedTags; + + private Map arguments; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getCodename() { + return codename; + } + + public void setCodename(String codename) { + this.codename = codename; + } + + public String getCondition() { + return condition; + } + + public void setCondition(String condition) { + this.condition = condition; + } + + public String getAction() { + return action; + } + + public void setAction(String action) { + this.action = action; + } + + public String getOption() { + return option; + } + + public void setOption(String option) { + this.option = option; + } + + public String getArgs() { + return args; + } + + public void setArgs(String args) { + this.args = args; + } + + public Map getArguments() { + return arguments; + } + + public void setArguments(Map arguments) { + this.arguments = arguments; + } + + public List getTags() { + return tagEntities; + } + + public void setTags(List tagEntities) { + this.tagEntities = tagEntities; + } + + public List getExcludedTags() { + return excludedTags; + } + + public void setExcludedTags(List excludedTags) { + this.excludedTags = excludedTags; + } + } diff --git a/src/main/java/org/karnak/backend/model/profilebody/ProfilePipeBody.java b/src/main/java/org/karnak/backend/model/profilebody/ProfilePipeBody.java index 42abfb7f8..64c74ed9d 100644 --- a/src/main/java/org/karnak/backend/model/profilebody/ProfilePipeBody.java +++ b/src/main/java/org/karnak/backend/model/profilebody/ProfilePipeBody.java @@ -13,58 +13,64 @@ public class ProfilePipeBody { - private String name; - private String version; - private String minimumKarnakVersion; - private String defaultIssuerOfPatientID; - private List profiles; - private List masks; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getVersion() { - return version; - } - - public void setVersion(String version) { - this.version = version; - } - - public String getMinimumKarnakVersion() { - return minimumKarnakVersion; - } - - public void setMinimumKarnakVersion(String minimumKarnakVersion) { - this.minimumKarnakVersion = minimumKarnakVersion; - } - - public List getProfileElements() { - return profiles; - } - - public void setProfileElements(List profiles) { - this.profiles = profiles; - } - - public String getDefaultIssuerOfPatientID() { - return defaultIssuerOfPatientID; - } - - public void setDefaultIssuerOfPatientID(String defaultIssuerOfPatientID) { - this.defaultIssuerOfPatientID = defaultIssuerOfPatientID; - } - - public List getMasks() { - return masks; - } - - public void setMasks(List masks) { - this.masks = masks; - } + private String name; + + private String version; + + private String minimumKarnakVersion; + + private String defaultIssuerOfPatientID; + + private List profiles; + + private List masks; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getMinimumKarnakVersion() { + return minimumKarnakVersion; + } + + public void setMinimumKarnakVersion(String minimumKarnakVersion) { + this.minimumKarnakVersion = minimumKarnakVersion; + } + + public List getProfileElements() { + return profiles; + } + + public void setProfileElements(List profiles) { + this.profiles = profiles; + } + + public String getDefaultIssuerOfPatientID() { + return defaultIssuerOfPatientID; + } + + public void setDefaultIssuerOfPatientID(String defaultIssuerOfPatientID) { + this.defaultIssuerOfPatientID = defaultIssuerOfPatientID; + } + + public List getMasks() { + return masks; + } + + public void setMasks(List masks) { + this.masks = masks; + } + } diff --git a/src/main/java/org/karnak/backend/model/profilepipe/HMAC.java b/src/main/java/org/karnak/backend/model/profilepipe/HMAC.java index 310b13ab6..db8d06fed 100644 --- a/src/main/java/org/karnak/backend/model/profilepipe/HMAC.java +++ b/src/main/java/org/karnak/backend/model/profilepipe/HMAC.java @@ -24,109 +24,111 @@ public class HMAC { - public static final int KEY_BYTE_LENGTH = 16; - private static final Logger LOGGER = LoggerFactory.getLogger(HMAC.class); - private static final String HMAC_SHA256 = "HmacSHA256"; - - private Mac mac; - private HashContext hashContext; - - public HMAC(byte[] hmacKey) { - initHMAC(hmacKey); - } - - public HMAC(HashContext hashContext) { - this.hashContext = hashContext; - initHMAC(hashContext.getSecret()); - } - - /* - * Generate a random secret key of 32bytes - * */ - public static byte[] generateRandomKey() { - SecureRandom random = new SecureRandom(); - byte[] bytes = new byte[KEY_BYTE_LENGTH]; - random.nextBytes(bytes); - return bytes; - } - - public static String byteToHex(byte[] key) { - return Hex.encodeHexString(key); - } - - public static String showHexKey(String key) { - return String.format( - "%s-%s-%s-%s-%s", - key.substring(0, 8), - key.substring(8, 12), - key.substring(12, 16), - key.substring(16, 20), - key.substring(20)); - } - - public static byte[] hexToByte(String hexKey) { - try { - return Hex.decodeHex(hexKey.replaceAll("-", "")); - } catch (DecoderException e) { - return null; - } - } - - public static boolean validateKey(String hexKey) { - String cleanHexKey = hexKey.replaceAll("-", ""); - if (cleanHexKey.length() == 32) { - return hexToByte(cleanHexKey) != null; - } - return false; - } - - private void initHMAC(byte[] keyValue) { - try { - SecretKeySpec key = new SecretKeySpec(keyValue, HMAC_SHA256); - this.mac = Mac.getInstance(HMAC_SHA256); - this.mac.init(key); - } catch (NoSuchAlgorithmException e) { - LOGGER.error("Invalid algorithm for the HMAC", e); - } catch (InvalidKeyException e) { - LOGGER.error("Invalid key for the HMAC init", e); - } - } - - // returns value in [scaleMin..scaleMax) - public double scaleHash(String value, int scaledMin, int scaledMax) { - final byte[] hash = new byte[6]; - final double max = 0x1000000000000L; - final double scale = scaledMax - (double) scaledMin; - - System.arraycopy(byteHash(value), 0, hash, 0, 6); - double fraction = new BigInteger(1, hash).doubleValue() / max; - return (int) (fraction * scale) + (double) scaledMin; - } - - public String uidHash(String inputUID) { - if (!StringUtil.hasText(inputUID)) { - throw new IllegalArgumentException(); - } - byte[] uuid = new byte[16]; - System.arraycopy(byteHash(inputUID), 0, uuid, 0, 16); - // https://en.wikipedia.org/wiki/Universally_unique_identifier - // GUID type 4 - // Version -> 4 - uuid[6] &= 0x0F; - uuid[6] |= 0x40; - // Variant 1 -> 10b - uuid[8] &= 0x3F; - uuid[8] |= 0x80; - return "2.25." + new BigInteger(1, uuid).toString(); - } - - public HashContext getHashContext() { - return hashContext; - } - - public byte[] byteHash(String value) { - byte[] bytes = null; - bytes = mac.doFinal(value.getBytes(StandardCharsets.US_ASCII)); - return bytes; - } + public static final int KEY_BYTE_LENGTH = 16; + + private static final Logger LOGGER = LoggerFactory.getLogger(HMAC.class); + + private static final String HMAC_SHA256 = "HmacSHA256"; + + private Mac mac; + + private HashContext hashContext; + + public HMAC(byte[] hmacKey) { + initHMAC(hmacKey); + } + + public HMAC(HashContext hashContext) { + this.hashContext = hashContext; + initHMAC(hashContext.getSecret()); + } + + /* + * Generate a random secret key of 32bytes + */ + public static byte[] generateRandomKey() { + SecureRandom random = new SecureRandom(); + byte[] bytes = new byte[KEY_BYTE_LENGTH]; + random.nextBytes(bytes); + return bytes; + } + + public static String byteToHex(byte[] key) { + return Hex.encodeHexString(key); + } + + public static String showHexKey(String key) { + return String.format("%s-%s-%s-%s-%s", key.substring(0, 8), key.substring(8, 12), key.substring(12, 16), + key.substring(16, 20), key.substring(20)); + } + + public static byte[] hexToByte(String hexKey) { + try { + return Hex.decodeHex(hexKey.replaceAll("-", "")); + } + catch (DecoderException e) { + return null; + } + } + + public static boolean validateKey(String hexKey) { + String cleanHexKey = hexKey.replaceAll("-", ""); + if (cleanHexKey.length() == 32) { + return hexToByte(cleanHexKey) != null; + } + return false; + } + + private void initHMAC(byte[] keyValue) { + try { + SecretKeySpec key = new SecretKeySpec(keyValue, HMAC_SHA256); + this.mac = Mac.getInstance(HMAC_SHA256); + this.mac.init(key); + } + catch (NoSuchAlgorithmException e) { + LOGGER.error("Invalid algorithm for the HMAC", e); + } + catch (InvalidKeyException e) { + LOGGER.error("Invalid key for the HMAC init", e); + } + } + + // returns value in [scaleMin..scaleMax) + public double scaleHash(String value, int scaledMin, int scaledMax) { + final byte[] hash = new byte[6]; + final double max = 0x1000000000000L; + final double scale = scaledMax - (double) scaledMin; + + System.arraycopy(byteHash(value), 0, hash, 0, 6); + double fraction = new BigInteger(1, hash).doubleValue() / max; + return (int) (fraction * scale) + (double) scaledMin; + } + + public String uidHash(String inputUID) { + if (!StringUtil.hasText(inputUID)) { + throw new IllegalArgumentException(); + } + byte[] uuid = new byte[16]; + System.arraycopy(byteHash(inputUID), 0, uuid, 0, 16); + // https://en.wikipedia.org/wiki/Universally_unique_identifier + // GUID type 4 + // Version -> 4 + uuid[6] &= 0x0F; + uuid[6] |= 0x40; + // Variant 1 -> 10b + uuid[8] &= 0x3F; + uuid[8] |= 0x80; + return "2.25." + new BigInteger(1, uuid); + } + + public HashContext getHashContext() { + return hashContext; + } + + public byte[] byteHash(String value) { + byte[] bytes = null; + bytes = mac.doFinal(value.getBytes(StandardCharsets.US_ASCII)); + return bytes; + } + } diff --git a/src/main/java/org/karnak/backend/model/profilepipe/HashContext.java b/src/main/java/org/karnak/backend/model/profilepipe/HashContext.java index 9f8c616bc..2c5f12f07 100644 --- a/src/main/java/org/karnak/backend/model/profilepipe/HashContext.java +++ b/src/main/java/org/karnak/backend/model/profilepipe/HashContext.java @@ -11,19 +11,21 @@ public class HashContext { - private final byte[] secret; - private final String PatientID; + private final byte[] secret; - public HashContext(byte[] secret, String PatientID) { - this.secret = secret; - this.PatientID = PatientID; - } + private final String PatientID; - public byte[] getSecret() { - return secret; - } + public HashContext(byte[] secret, String PatientID) { + this.secret = secret; + this.PatientID = PatientID; + } + + public byte[] getSecret() { + return secret; + } + + public String getPatientID() { + return PatientID; + } - public String getPatientID() { - return PatientID; - } } diff --git a/src/main/java/org/karnak/backend/model/profilepipe/PatientMetadata.java b/src/main/java/org/karnak/backend/model/profilepipe/PatientMetadata.java index b4cafd4ae..5a8eb2b46 100644 --- a/src/main/java/org/karnak/backend/model/profilepipe/PatientMetadata.java +++ b/src/main/java/org/karnak/backend/model/profilepipe/PatientMetadata.java @@ -18,90 +18,93 @@ public class PatientMetadata { - private static final String PATIENT_SEX_OTHER = "O"; - - private final String patientID; - private final String patientName; - private final String patientBirthDate; - private final String issuerOfPatientID; - private final String patientSex; - - public PatientMetadata(Attributes dcm) { - patientID = dcm.getString(Tag.PatientID, ""); - patientName = dcm.getString(Tag.PatientName, ""); - patientBirthDate = setPatientBirthDate(dcm.getString(Tag.PatientBirthDate)); - issuerOfPatientID = ""; - patientSex = setPatientSex(dcm.getString(Tag.PatientSex, PATIENT_SEX_OTHER)); - } - - public PatientMetadata(Attributes dcm, String issuerOfPatientIDByDefault) { - patientID = dcm.getString(Tag.PatientID, ""); - patientName = dcm.getString(Tag.PatientName, ""); - patientBirthDate = setPatientBirthDate(dcm.getString(Tag.PatientBirthDate)); - issuerOfPatientID = dcm.getString(Tag.IssuerOfPatientID, issuerOfPatientIDByDefault); - patientSex = setPatientSex(dcm.getString(Tag.PatientSex, PATIENT_SEX_OTHER)); - } - - private String setPatientSex(String patientSex) { - if (!patientSex.equals("M") && !patientSex.equals("F")) { - return PATIENT_SEX_OTHER; - } - return patientSex; - } - - private String setPatientBirthDate(String rawPatientBirthDate) { - return DateUtil.formatDicomDate(DateUtil.getDicomDate(rawPatientBirthDate)); - } - - public String getPatientID() { - return patientID; - } - - public String getPatientName() { - return patientName; - } - - public String getPatientLastName() { - return patientName.split("\\^")[0]; - } - - public String getPatientFirstName() { - String[] patientNameSplitted = patientName.split("\\^"); - if (patientNameSplitted.length > 1) { - return patientNameSplitted[1]; - } - return ""; - } - - public String getPatientBirthDate() { - return patientBirthDate; - } - - public LocalDate getLocalDatePatientBirthDate() { - return DateUtil.getDicomDate(patientBirthDate); - } - - public String getIssuerOfPatientID() { - return issuerOfPatientID; - } - - public String getPatientSex() { - return patientSex; - } - - public boolean compareCachedPatient(PseudonymPatient patient) { - if (patient != null) { - boolean samePatient = patient.getPatientId().equals(patientID); - samePatient = - samePatient - && (patient.getIssuerOfPatientId() == null - || patient.getIssuerOfPatientId().equals(issuerOfPatientID)); - return samePatient; - } - return false; - } - - public Fields generateMainzellisteFields() { - return new Fields(patientID, patientName, patientBirthDate, patientSex, issuerOfPatientID); - } + private static final String PATIENT_SEX_OTHER = "O"; + + private final String patientID; + + private final String patientName; + + private final String patientBirthDate; + + private final String issuerOfPatientID; + + private final String patientSex; + + public PatientMetadata(Attributes dcm) { + patientID = dcm.getString(Tag.PatientID, ""); + patientName = dcm.getString(Tag.PatientName, ""); + patientBirthDate = setPatientBirthDate(dcm.getString(Tag.PatientBirthDate)); + issuerOfPatientID = ""; + patientSex = setPatientSex(dcm.getString(Tag.PatientSex, PATIENT_SEX_OTHER)); + } + + public PatientMetadata(Attributes dcm, String issuerOfPatientIDByDefault) { + patientID = dcm.getString(Tag.PatientID, ""); + patientName = dcm.getString(Tag.PatientName, ""); + patientBirthDate = setPatientBirthDate(dcm.getString(Tag.PatientBirthDate)); + issuerOfPatientID = dcm.getString(Tag.IssuerOfPatientID, issuerOfPatientIDByDefault); + patientSex = setPatientSex(dcm.getString(Tag.PatientSex, PATIENT_SEX_OTHER)); + } + + private String setPatientSex(String patientSex) { + if (!patientSex.equals("M") && !patientSex.equals("F")) { + return PATIENT_SEX_OTHER; + } + return patientSex; + } + + private String setPatientBirthDate(String rawPatientBirthDate) { + return DateUtil.formatDicomDate(DateUtil.getDicomDate(rawPatientBirthDate)); + } + + public String getPatientID() { + return patientID; + } + + public String getPatientName() { + return patientName; + } + + public String getPatientLastName() { + return patientName.split("\\^")[0]; + } + + public String getPatientFirstName() { + String[] patientNameSplitted = patientName.split("\\^"); + if (patientNameSplitted.length > 1) { + return patientNameSplitted[1]; + } + return ""; + } + + public String getPatientBirthDate() { + return patientBirthDate; + } + + public LocalDate getLocalDatePatientBirthDate() { + return DateUtil.getDicomDate(patientBirthDate); + } + + public String getIssuerOfPatientID() { + return issuerOfPatientID; + } + + public String getPatientSex() { + return patientSex; + } + + public boolean compareCachedPatient(PseudonymPatient patient) { + if (patient != null) { + boolean samePatient = patient.getPatientId().equals(patientID); + samePatient = samePatient && (patient.getIssuerOfPatientId() == null + || patient.getIssuerOfPatientId().equals(issuerOfPatientID)); + return samePatient; + } + return false; + } + + public Fields generateMainzellisteFields() { + return new Fields(patientID, patientName, patientBirthDate, patientSex, issuerOfPatientID); + } + } diff --git a/src/main/java/org/karnak/backend/model/profilepipe/TagActionMap.java b/src/main/java/org/karnak/backend/model/profilepipe/TagActionMap.java index 8127418be..e1b6ba19b 100644 --- a/src/main/java/org/karnak/backend/model/profilepipe/TagActionMap.java +++ b/src/main/java/org/karnak/backend/model/profilepipe/TagActionMap.java @@ -17,64 +17,68 @@ public class TagActionMap { - private final HashMap tagAction; - private final HashMap tagPatternAction; + private final HashMap tagAction; - public TagActionMap() { - tagAction = new HashMap<>(); - tagPatternAction = new HashMap<>(); - } + private final HashMap tagPatternAction; - public static boolean isValidPattern(String tagPattern) { - if (!StringUtil.hasText(tagPattern) || tagPattern.length() != 8) { - return false; - } - String p = tagPattern.toUpperCase(); - return p.matches("[0-9A-FX]+") && p.contains("X"); - } + public TagActionMap() { + tagAction = new HashMap<>(); + tagPatternAction = new HashMap<>(); + } - public static String getMask(String tagPattern) { - char[] chars = tagPattern.toUpperCase().toCharArray(); - for (int i = 0; i < chars.length; i++) { - if (chars[i] == 'X') { - chars[i] = '0'; - } else { - chars[i] = 'F'; - } - } - return new String(chars); - } + public static boolean isValidPattern(String tagPattern) { + if (!StringUtil.hasText(tagPattern) || tagPattern.length() != 8) { + return false; + } + String p = tagPattern.toUpperCase(); + return p.matches("[0-9A-FX]+") && p.contains("X"); + } - public void put(String tag, ActionItem action) { - String cleanTag = tag.replaceAll("[(),]", "").toUpperCase(); - if (isValidPattern(cleanTag)) { - tagPatternAction.put(cleanTag, action); - } else { - tagAction.put(TagUtils.intFromHexString(cleanTag), action); - } - } + public static String getMask(String tagPattern) { + char[] chars = tagPattern.toUpperCase().toCharArray(); + for (int i = 0; i < chars.length; i++) { + if (chars[i] == 'X') { + chars[i] = '0'; + } + else { + chars[i] = 'F'; + } + } + return new String(chars); + } - public ActionItem get(Integer tag) { - ActionItem action = tagAction.get(tag); - if (action == null) { - for (Map.Entry entry : tagPatternAction.entrySet()) { - String currentTagPattern = entry.getKey(); - int patternTag = TagUtils.intFromHexString(currentTagPattern.replace("X", "0")); - int patternMask = TagUtils.intFromHexString(getMask(currentTagPattern)); + public void put(String tag, ActionItem action) { + String cleanTag = tag.replaceAll("[(),]", "").toUpperCase(); + if (isValidPattern(cleanTag)) { + tagPatternAction.put(cleanTag, action); + } + else { + tagAction.put(TagUtils.intFromHexString(cleanTag), action); + } + } - if ((tag & patternMask) == patternTag) { - return entry.getValue(); - } - } - } - return action; - } + public ActionItem get(Integer tag) { + ActionItem action = tagAction.get(tag); + if (action == null) { + for (Map.Entry entry : tagPatternAction.entrySet()) { + String currentTagPattern = entry.getKey(); + int patternTag = TagUtils.intFromHexString(currentTagPattern.replace("X", "0")); + int patternMask = TagUtils.intFromHexString(getMask(currentTagPattern)); - public int size() { - return this.tagAction.size() + this.tagPatternAction.size(); - } + if ((tag & patternMask) == patternTag) { + return entry.getValue(); + } + } + } + return action; + } + + public int size() { + return this.tagAction.size() + this.tagPatternAction.size(); + } + + public boolean isEmpty() { + return this.tagAction.isEmpty() && this.tagPatternAction.isEmpty(); + } - public boolean isEmpty() { - return this.tagAction.isEmpty() && this.tagPatternAction.isEmpty(); - } } diff --git a/src/main/java/org/karnak/backend/model/profiles/AbstractProfileItem.java b/src/main/java/org/karnak/backend/model/profiles/AbstractProfileItem.java index 57aecf4f2..3cc3805a8 100644 --- a/src/main/java/org/karnak/backend/model/profiles/AbstractProfileItem.java +++ b/src/main/java/org/karnak/backend/model/profiles/AbstractProfileItem.java @@ -24,81 +24,90 @@ public abstract class AbstractProfileItem implements ProfileItem { - protected final String name; - protected final String codeName; - protected final String condition; - protected final String action; - protected final String option; - protected final List argumentEntities; - protected final List tagEntities; - protected final List excludedTagEntities; - protected final Map tagMap; - protected final Integer position; - - protected AbstractProfileItem(ProfileElementEntity profileElementEntity) { - this.name = Objects.requireNonNull(profileElementEntity.getName()); - this.codeName = Objects.requireNonNull(profileElementEntity.getCodename()); - this.condition = profileElementEntity.getCondition(); - this.action = profileElementEntity.getAction(); - this.option = profileElementEntity.getOption(); - this.argumentEntities = profileElementEntity.getArgumentEntities(); - this.tagEntities = profileElementEntity.getIncludedTagEntities(); - this.excludedTagEntities = profileElementEntity.getExcludedTagEntities(); - this.position = profileElementEntity.getPosition(); - this.tagMap = new HashMap<>(); - } - - public String getName() { - return name; - } - - public String getCodeName() { - return codeName; - } - - public String getCondition() { - return condition; - } - - public String getOption() { - return option; - } - - public List getArguments() { - return argumentEntities; - } - - public Integer getPosition() { - return position; - } - - @Override - public String toString() { - return name; - } - - @Override - public void clearTagMap() { - tagMap.clear(); - } - - @Override - public ActionItem remove(int tag) { - return tagMap.remove(tag); - } - - @Override - public ActionItem put(int tag, ActionItem action) { - Objects.requireNonNull(action); - return tagMap.put(tag, action); - } - - @Override - public void profileValidation() throws Exception { - ExpressionError expressionError = - ExpressionResult.isValid(condition, new ExprCondition(), Boolean.class); - if (condition != null && !expressionError.isValid()) { - throw new Exception(expressionError.getMsg()); - } - } + protected final String name; + + protected final String codeName; + + protected final String condition; + + protected final String action; + + protected final String option; + + protected final List argumentEntities; + + protected final List tagEntities; + + protected final List excludedTagEntities; + + protected final Map tagMap; + + protected final Integer position; + + protected AbstractProfileItem(ProfileElementEntity profileElementEntity) { + this.name = Objects.requireNonNull(profileElementEntity.getName()); + this.codeName = Objects.requireNonNull(profileElementEntity.getCodename()); + this.condition = profileElementEntity.getCondition(); + this.action = profileElementEntity.getAction(); + this.option = profileElementEntity.getOption(); + this.argumentEntities = profileElementEntity.getArgumentEntities(); + this.tagEntities = profileElementEntity.getIncludedTagEntities(); + this.excludedTagEntities = profileElementEntity.getExcludedTagEntities(); + this.position = profileElementEntity.getPosition(); + this.tagMap = new HashMap<>(); + } + + public String getName() { + return name; + } + + public String getCodeName() { + return codeName; + } + + public String getCondition() { + return condition; + } + + public String getOption() { + return option; + } + + public List getArguments() { + return argumentEntities; + } + + public Integer getPosition() { + return position; + } + + @Override + public String toString() { + return name; + } + + @Override + public void clearTagMap() { + tagMap.clear(); + } + + @Override + public ActionItem remove(int tag) { + return tagMap.remove(tag); + } + + @Override + public ActionItem put(int tag, ActionItem action) { + Objects.requireNonNull(action); + return tagMap.put(tag, action); + } + + @Override + public void profileValidation() throws Exception { + ExpressionError expressionError = ExpressionResult.isValid(condition, new ExprCondition(), Boolean.class); + if (condition != null && !expressionError.isValid()) { + throw new Exception(expressionError.getMsg()); + } + } + } diff --git a/src/main/java/org/karnak/backend/model/profiles/ActionDates.java b/src/main/java/org/karnak/backend/model/profiles/ActionDates.java index 76972c7e6..dd414165c 100644 --- a/src/main/java/org/karnak/backend/model/profiles/ActionDates.java +++ b/src/main/java/org/karnak/backend/model/profiles/ActionDates.java @@ -31,102 +31,98 @@ public class ActionDates extends AbstractProfileItem { - private static final Logger LOGGER = LoggerFactory.getLogger(ActionDates.class); + private static final Logger LOGGER = LoggerFactory.getLogger(ActionDates.class); - private final TagActionMap tagsAction; - private final TagActionMap exceptedTagsAction; - private final ActionItem actionByDefault; + private final TagActionMap tagsAction; - public ActionDates(ProfileElementEntity profileElementEntity) throws Exception { - super(profileElementEntity); - tagsAction = new TagActionMap(); - exceptedTagsAction = new TagActionMap(); - actionByDefault = new Replace("D"); - profileValidation(); - setActionHashMap(); - } + private final TagActionMap exceptedTagsAction; - private void setActionHashMap() throws Exception { - if (tagEntities != null && tagEntities.size() > 0) { - for (IncludedTagEntity tag : tagEntities) { - tagsAction.put(tag.getTagValue(), actionByDefault); - } - } - if (excludedTagEntities != null && excludedTagEntities.size() > 0) { - for (ExcludedTagEntity tag : excludedTagEntities) { - exceptedTagsAction.put(tag.getTagValue(), actionByDefault); - } - } - } + private final ActionItem actionByDefault; - @Override - public void profileValidation() throws Exception { - try { - if (option == null) { - throw new Exception( - "Cannot build the profile " - + codeName - + " : An option must be given. Option available: [shift, shift_range]"); - } - switch (option) { - case "shift" -> ShiftDate.verifyShiftArguments(argumentEntities); - case "shift_range" -> ShiftRangeDate.verifyShiftArguments(argumentEntities); - case "date_format" -> DateFormat.verifyPatternArguments(argumentEntities); - default -> throw new Exception( - "Cannot build the profile " - + codeName - + " with the option given " - + option - + " : Option available (shift, shift_range)"); - } - } catch (Exception e) { - throw e; - } + public ActionDates(ProfileElementEntity profileElementEntity) throws Exception { + super(profileElementEntity); + tagsAction = new TagActionMap(); + exceptedTagsAction = new TagActionMap(); + actionByDefault = new Replace("D"); + profileValidation(); + setActionHashMap(); + } - final ExpressionError expressionError = - ExpressionResult.isValid(condition, new ExprCondition(new Attributes()), Boolean.class); - if (condition != null && !expressionError.isValid()) { - throw new Exception(expressionError.getMsg()); - } - } + private void setActionHashMap() throws Exception { + if (tagEntities != null && tagEntities.size() > 0) { + for (IncludedTagEntity tag : tagEntities) { + tagsAction.put(tag.getTagValue(), actionByDefault); + } + } + if (excludedTagEntities != null && excludedTagEntities.size() > 0) { + for (ExcludedTagEntity tag : excludedTagEntities) { + exceptedTagsAction.put(tag.getTagValue(), actionByDefault); + } + } + } - @Override - public ActionItem getAction(Attributes dcm, Attributes dcmCopy, int tag, HMAC hmac) { - final VR vr = dcm.getVR(tag); + @Override + public void profileValidation() throws Exception { + try { + if (option == null) { + throw new Exception("Cannot build the profile " + codeName + + " : An option must be given. Option available: [shift, shift_range]"); + } + switch (option) { + case "shift" -> ShiftDate.verifyShiftArguments(argumentEntities); + case "shift_range" -> ShiftRangeDate.verifyShiftArguments(argumentEntities); + case "date_format" -> DateFormat.verifyPatternArguments(argumentEntities); + default -> throw new Exception("Cannot build the profile " + codeName + " with the option given " + option + + " : Option available (shift, shift_range)"); + } + } + catch (Exception e) { + throw e; + } - if (vr == VR.AS || vr == VR.DA || vr == VR.DT || vr == VR.TM) { - if (exceptedTagsAction.get(tag) != null) { - return null; - } + final ExpressionError expressionError = ExpressionResult.isValid(condition, new ExprCondition(new Attributes()), + Boolean.class); + if (condition != null && !expressionError.isValid()) { + throw new Exception(expressionError.getMsg()); + } + } - if (!tagsAction.isEmpty() && tagsAction.get(tag) == null) { - return null; - } - try { - String dummyValue = applyOption(dcmCopy, tag, hmac); - if (dummyValue != null) { - actionByDefault.setDummyValue(dummyValue); - return actionByDefault; - } - } catch (DateTimeException dateTimeException) { - String dcmElValue = dcmCopy.getString(tag); - LOGGER.warn( - String.format( - "Invalid date %s, the most strictest action will be choose between X/Z/D", - dcmElValue), - dateTimeException); - return new MultipleActions("X/Z/D"); - } - } - return null; - } + @Override + public ActionItem getAction(Attributes dcm, Attributes dcmCopy, int tag, HMAC hmac) { + final VR vr = dcm.getVR(tag); + + if (vr == VR.AS || vr == VR.DA || vr == VR.DT || vr == VR.TM) { + if (exceptedTagsAction.get(tag) != null) { + return null; + } + + if (!tagsAction.isEmpty() && tagsAction.get(tag) == null) { + return null; + } + try { + String dummyValue = applyOption(dcmCopy, tag, hmac); + if (dummyValue != null) { + actionByDefault.setDummyValue(dummyValue); + return actionByDefault; + } + } + catch (DateTimeException dateTimeException) { + String dcmElValue = dcmCopy.getString(tag); + LOGGER.warn(String.format("Invalid date %s, the most strictest action will be choose between X/Z/D", + dcmElValue), dateTimeException); + return new MultipleActions("X/Z/D"); + } + } + return null; + } + + private String applyOption(Attributes dcmCopy, int tag, HMAC hmac) throws DateTimeException { + return switch (option) { + case "shift" -> ShiftDate.shift(dcmCopy, tag, argumentEntities); + case "shift_range" -> ShiftRangeDate.shift(dcmCopy, tag, argumentEntities, hmac); + case "date_format" -> DateFormat.format(dcmCopy, tag, argumentEntities); + default -> null; + }; + } - private String applyOption(Attributes dcmCopy, int tag, HMAC hmac) throws DateTimeException { - return switch (option) { - case "shift" -> ShiftDate.shift(dcmCopy, tag, argumentEntities); - case "shift_range" -> ShiftRangeDate.shift(dcmCopy, tag, argumentEntities, hmac); - case "date_format" -> DateFormat.format(dcmCopy, tag, argumentEntities); - default -> null; - }; - } } diff --git a/src/main/java/org/karnak/backend/model/profiles/ActionTags.java b/src/main/java/org/karnak/backend/model/profiles/ActionTags.java index 833116aa2..11010d0dc 100644 --- a/src/main/java/org/karnak/backend/model/profiles/ActionTags.java +++ b/src/main/java/org/karnak/backend/model/profiles/ActionTags.java @@ -26,79 +26,83 @@ public class ActionTags extends AbstractProfileItem { - private static final Logger LOGGER = LoggerFactory.getLogger(ActionTags.class); - - private final TagActionMap tagsAction; - private final TagActionMap exceptedTagsAction; - private final ActionItem actionByDefault; - - public ActionTags(ProfileElementEntity profileElementEntity) throws Exception { - super(profileElementEntity); - tagsAction = new TagActionMap(); - exceptedTagsAction = new TagActionMap(); - actionByDefault = AbstractAction.convertAction(this.action); - profileValidation(); - setActionHashMap(); - } - - public static String color2Hexadecimal(Color c, boolean alpha) { - int val = c == null ? 0 : alpha ? c.getRGB() : c.getRGB() & 0x00ffffff; - return Integer.toHexString(val); - } - - public static Color hexadecimal2Color(String hexColor) { - int intValue = 0xff000000; - - try { - if (hexColor != null && hexColor.length() > 6) { - intValue = (int) (Long.parseLong(hexColor, 16) & 0xffffffff); - } else { - intValue |= Integer.parseInt(hexColor, 16); - } - } catch (NumberFormatException e) { - LOGGER.error("Cannot parse color {} into int", hexColor); // $NON-NLS-1$ - } - return new Color(intValue, true); - } - - private void setActionHashMap() throws Exception { - for (IncludedTagEntity tag : tagEntities) { - tagsAction.put(tag.getTagValue(), actionByDefault); - } - if (excludedTagEntities != null) { - for (ExcludedTagEntity tag : excludedTagEntities) { - exceptedTagsAction.put(tag.getTagValue(), actionByDefault); - } - } - } - - @Override - public ActionItem getAction(Attributes dcm, Attributes dcmCopy, int tag, HMAC hmac) { - if (exceptedTagsAction.get(tag) == null) { - return tagsAction.get(tag); - } - return null; - } - - @Override - public void profileValidation() throws Exception { - if (action == null && (tagEntities == null || tagEntities.size() <= 0)) { - throw new Exception( - "Cannot build the profile " + codeName + ": Unknown Action and no tags defined"); - } - - if (action == null) { - throw new Exception("Cannot build the profile " + codeName + ": Unknown Action"); - } - - if (tagEntities == null || tagEntities.size() <= 0) { - throw new Exception("Cannot build the profile " + codeName + ": No tags defined"); - } - - final ExpressionError expressionError = - ExpressionResult.isValid(condition, new ExprCondition(new Attributes()), Boolean.class); - if (condition != null && !expressionError.isValid()) { - throw new Exception(expressionError.getMsg()); - } - } + private static final Logger LOGGER = LoggerFactory.getLogger(ActionTags.class); + + private final TagActionMap tagsAction; + + private final TagActionMap exceptedTagsAction; + + private final ActionItem actionByDefault; + + public ActionTags(ProfileElementEntity profileElementEntity) throws Exception { + super(profileElementEntity); + tagsAction = new TagActionMap(); + exceptedTagsAction = new TagActionMap(); + actionByDefault = AbstractAction.convertAction(this.action); + profileValidation(); + setActionHashMap(); + } + + public static String color2Hexadecimal(Color c, boolean alpha) { + int val = c == null ? 0 : alpha ? c.getRGB() : c.getRGB() & 0x00ffffff; + return Integer.toHexString(val); + } + + public static Color hexadecimal2Color(String hexColor) { + int intValue = 0xff000000; + + try { + if (hexColor != null && hexColor.length() > 6) { + intValue = (int) (Long.parseLong(hexColor, 16) & 0xffffffff); + } + else { + intValue |= Integer.parseInt(hexColor, 16); + } + } + catch (NumberFormatException e) { + LOGGER.error("Cannot parse color {} into int", hexColor); // $NON-NLS-1$ + } + return new Color(intValue, true); + } + + private void setActionHashMap() throws Exception { + for (IncludedTagEntity tag : tagEntities) { + tagsAction.put(tag.getTagValue(), actionByDefault); + } + if (excludedTagEntities != null) { + for (ExcludedTagEntity tag : excludedTagEntities) { + exceptedTagsAction.put(tag.getTagValue(), actionByDefault); + } + } + } + + @Override + public ActionItem getAction(Attributes dcm, Attributes dcmCopy, int tag, HMAC hmac) { + if (exceptedTagsAction.get(tag) == null) { + return tagsAction.get(tag); + } + return null; + } + + @Override + public void profileValidation() throws Exception { + if (action == null && (tagEntities == null || tagEntities.size() <= 0)) { + throw new Exception("Cannot build the profile " + codeName + ": Unknown Action and no tags defined"); + } + + if (action == null) { + throw new Exception("Cannot build the profile " + codeName + ": Unknown Action"); + } + + if (tagEntities == null || tagEntities.size() <= 0) { + throw new Exception("Cannot build the profile " + codeName + ": No tags defined"); + } + + final ExpressionError expressionError = ExpressionResult.isValid(condition, new ExprCondition(new Attributes()), + Boolean.class); + if (condition != null && !expressionError.isValid()) { + throw new Exception(expressionError.getMsg()); + } + } + } diff --git a/src/main/java/org/karnak/backend/model/profiles/BasicProfile.java b/src/main/java/org/karnak/backend/model/profiles/BasicProfile.java index 24f930b18..f8ddd061e 100644 --- a/src/main/java/org/karnak/backend/model/profiles/BasicProfile.java +++ b/src/main/java/org/karnak/backend/model/profiles/BasicProfile.java @@ -20,29 +20,30 @@ public class BasicProfile extends AbstractProfileItem { - private final List listProfiles; - private final TagActionMap actionMap; + private final List listProfiles; - public BasicProfile(ProfileElementEntity profileElementEntity) { - super(profileElementEntity); - ConfidentialityProfiles confidentialityProfiles = - AppConfig.getInstance().getConfidentialityProfile(); - actionMap = confidentialityProfiles.getActionMap(); - listProfiles = confidentialityProfiles.getListProfiles(); - } + private final TagActionMap actionMap; + + public BasicProfile(ProfileElementEntity profileElementEntity) { + super(profileElementEntity); + ConfidentialityProfiles confidentialityProfiles = AppConfig.getInstance().getConfidentialityProfile(); + actionMap = confidentialityProfiles.getActionMap(); + listProfiles = confidentialityProfiles.getListProfiles(); + } + + @Override + public ActionItem getAction(Attributes dcm, Attributes dcmCopy, int tag, HMAC hmac) { + ActionItem action = actionMap.get(tag); + if (action == null) { + for (ProfileItem p : listProfiles) { + ActionItem val = p.getAction(dcm, dcmCopy, tag, hmac); + if (val != null) { + return val; + } + } + return null; + } + return action; + } - @Override - public ActionItem getAction(Attributes dcm, Attributes dcmCopy, int tag, HMAC hmac) { - ActionItem action = actionMap.get(tag); - if (action == null) { - for (ProfileItem p : listProfiles) { - ActionItem val = p.getAction(dcm, dcmCopy, tag, hmac); - if (val != null) { - return val; - } - } - return null; - } - return action; - } } diff --git a/src/main/java/org/karnak/backend/model/profiles/CleanPixelData.java b/src/main/java/org/karnak/backend/model/profiles/CleanPixelData.java index 9231c1060..61f1132f1 100644 --- a/src/main/java/org/karnak/backend/model/profiles/CleanPixelData.java +++ b/src/main/java/org/karnak/backend/model/profiles/CleanPixelData.java @@ -16,14 +16,15 @@ public class CleanPixelData extends AbstractProfileItem { - public CleanPixelData(ProfileElementEntity profileElementEntity) throws Exception { - super(profileElementEntity); - profileValidation(); - } + public CleanPixelData(ProfileElementEntity profileElementEntity) throws Exception { + super(profileElementEntity); + profileValidation(); + } + + @Override + public ActionItem getAction(Attributes dcm, Attributes dcmCopy, int tag, HMAC hmac) { + // Action handles in the DICOM content not in metadata. + return null; + } - @Override - public ActionItem getAction(Attributes dcm, Attributes dcmCopy, int tag, HMAC hmac) { - // Action handles in the DICOM content not in metadata. - return null; - } } diff --git a/src/main/java/org/karnak/backend/model/profiles/Defacing.java b/src/main/java/org/karnak/backend/model/profiles/Defacing.java index 7088881bd..e850d33ca 100644 --- a/src/main/java/org/karnak/backend/model/profiles/Defacing.java +++ b/src/main/java/org/karnak/backend/model/profiles/Defacing.java @@ -16,14 +16,15 @@ public class Defacing extends AbstractProfileItem { - public Defacing(ProfileElementEntity profileElementEntity) throws Exception { - super(profileElementEntity); - profileValidation(); - } + public Defacing(ProfileElementEntity profileElementEntity) throws Exception { + super(profileElementEntity); + profileValidation(); + } + + @Override + public ActionItem getAction(Attributes dcm, Attributes dcmCopy, int tag, HMAC hmac) { + // Action handles in the DICOM content not in metadata. + return null; + } - @Override - public ActionItem getAction(Attributes dcm, Attributes dcmCopy, int tag, HMAC hmac) { - // Action handles in the DICOM content not in metadata. - return null; - } } diff --git a/src/main/java/org/karnak/backend/model/profiles/Expression.java b/src/main/java/org/karnak/backend/model/profiles/Expression.java index 70a1cecea..7087595c1 100644 --- a/src/main/java/org/karnak/backend/model/profiles/Expression.java +++ b/src/main/java/org/karnak/backend/model/profiles/Expression.java @@ -27,59 +27,60 @@ public class Expression extends AbstractProfileItem { - private final TagActionMap tagsAction; - private final TagActionMap exceptedTagsAction; - private final ActionItem actionByDefault; + private final TagActionMap tagsAction; - public Expression(ProfileElementEntity profileElementEntity) throws Exception { - super(profileElementEntity); - tagsAction = new TagActionMap(); - exceptedTagsAction = new TagActionMap(); - actionByDefault = AbstractAction.convertAction("K"); - profileValidation(); - setActionHashMap(); - } + private final TagActionMap exceptedTagsAction; - private void setActionHashMap() throws Exception { - if (tagEntities != null) { - for (IncludedTagEntity tag : tagEntities) { - tagsAction.put(tag.getTagValue(), actionByDefault); - } - if (excludedTagEntities != null) { - for (ExcludedTagEntity tag : excludedTagEntities) { - exceptedTagsAction.put(tag.getTagValue(), actionByDefault); - } - } - } - } + private final ActionItem actionByDefault; - @Override - public ActionItem getAction(Attributes dcm, Attributes dcmCopy, int tag, HMAC hmac) { - if (exceptedTagsAction.get(tag) == null && tagsAction.get(tag) != null) { - final String expr = argumentEntities.get(0).getValue(); - final ExprAction exprAction = new ExprAction(tag, dcm.getVR(tag), dcm, dcmCopy); - return (ActionItem) ExpressionResult.get(expr, exprAction, ActionItem.class); - } - return null; - } + public Expression(ProfileElementEntity profileElementEntity) throws Exception { + super(profileElementEntity); + tagsAction = new TagActionMap(); + exceptedTagsAction = new TagActionMap(); + actionByDefault = AbstractAction.convertAction("K"); + profileValidation(); + setActionHashMap(); + } - public void profileValidation() throws Exception { - if (!argumentEntities.stream().anyMatch(argument -> argument.getKey().equals("expr"))) { - List args = - argumentEntities.stream().map(ArgumentEntity::getKey).collect(Collectors.toList()); - throw new IllegalArgumentException( - "Cannot build the expression: Missing argument, the class need [expr] as parameters. Parameters given " - + args); - } + private void setActionHashMap() throws Exception { + if (tagEntities != null) { + for (IncludedTagEntity tag : tagEntities) { + tagsAction.put(tag.getTagValue(), actionByDefault); + } + if (excludedTagEntities != null) { + for (ExcludedTagEntity tag : excludedTagEntities) { + exceptedTagsAction.put(tag.getTagValue(), actionByDefault); + } + } + } + } - final String expr = argumentEntities.get(0).getValue(); - final ExpressionError expressionError = - ExpressionResult.isValid( - expr, new ExprAction(1, VR.AE, new Attributes(), new Attributes()), ActionItem.class); + @Override + public ActionItem getAction(Attributes dcm, Attributes dcmCopy, int tag, HMAC hmac) { + if (exceptedTagsAction.get(tag) == null && tagsAction.get(tag) != null) { + final String expr = argumentEntities.get(0).getValue(); + final ExprAction exprAction = new ExprAction(tag, dcm.getVR(tag), dcm, dcmCopy); + return (ActionItem) ExpressionResult.get(expr, exprAction, ActionItem.class); + } + return null; + } + + public void profileValidation() throws Exception { + if (!argumentEntities.stream().anyMatch(argument -> argument.getKey().equals("expr"))) { + List args = argumentEntities.stream().map(ArgumentEntity::getKey).collect(Collectors.toList()); + throw new IllegalArgumentException( + "Cannot build the expression: Missing argument, the class need [expr] as parameters. Parameters given " + + args); + } + + final String expr = argumentEntities.get(0).getValue(); + final ExpressionError expressionError = ExpressionResult.isValid(expr, + new ExprAction(1, VR.AE, new Attributes(), new Attributes()), ActionItem.class); + + if (!expressionError.isValid()) { + throw new IllegalArgumentException( + String.format("Expression is not valid: \n\r%s", expressionError.getMsg())); + } + } - if (!expressionError.isValid()) { - throw new IllegalArgumentException( - String.format("Expression is not valid: \n\r%s", expressionError.getMsg())); - } - } } diff --git a/src/main/java/org/karnak/backend/model/profiles/PrivateTags.java b/src/main/java/org/karnak/backend/model/profiles/PrivateTags.java index cb873b701..a59fb2248 100644 --- a/src/main/java/org/karnak/backend/model/profiles/PrivateTags.java +++ b/src/main/java/org/karnak/backend/model/profiles/PrivateTags.java @@ -26,69 +26,72 @@ public class PrivateTags extends AbstractProfileItem { - private static final Logger LOGGER = LoggerFactory.getLogger(PrivateTags.class); + private static final Logger LOGGER = LoggerFactory.getLogger(PrivateTags.class); - private final TagActionMap tagsAction; - private final TagActionMap exceptedTagsAction; - private final ActionItem actionByDefault; + private final TagActionMap tagsAction; - public PrivateTags(ProfileElementEntity profileElementEntity) throws Exception { - super(profileElementEntity); - tagsAction = new TagActionMap(); - exceptedTagsAction = new TagActionMap(); - actionByDefault = AbstractAction.convertAction(this.action); - profileValidation(); - setActionHashMap(); - } + private final TagActionMap exceptedTagsAction; - private void setActionHashMap() throws Exception { + private final ActionItem actionByDefault; - if (tagEntities != null && tagEntities.size() > 0) { - for (IncludedTagEntity tag : tagEntities) { - tagsAction.put(tag.getTagValue(), actionByDefault); - } - } - if (excludedTagEntities != null && excludedTagEntities.size() > 0) { - for (ExcludedTagEntity tag : excludedTagEntities) { - exceptedTagsAction.put(tag.getTagValue(), actionByDefault); - } - } - } + public PrivateTags(ProfileElementEntity profileElementEntity) throws Exception { + super(profileElementEntity); + tagsAction = new TagActionMap(); + exceptedTagsAction = new TagActionMap(); + actionByDefault = AbstractAction.convertAction(this.action); + profileValidation(); + setActionHashMap(); + } - @Override - public ActionItem getAction(Attributes dcm, Attributes dcmCopy, int tag, HMAC hmac) { - if (TagUtils.isPrivateGroup(tag)) { - if (!tagsAction.isEmpty() && exceptedTagsAction.isEmpty()) { - return tagsAction.get(tag); - } + private void setActionHashMap() throws Exception { - if (tagsAction.isEmpty() && !exceptedTagsAction.isEmpty()) { - if (exceptedTagsAction.get(tag) != null) { - return null; - } - } + if (tagEntities != null && tagEntities.size() > 0) { + for (IncludedTagEntity tag : tagEntities) { + tagsAction.put(tag.getTagValue(), actionByDefault); + } + } + if (excludedTagEntities != null && excludedTagEntities.size() > 0) { + for (ExcludedTagEntity tag : excludedTagEntities) { + exceptedTagsAction.put(tag.getTagValue(), actionByDefault); + } + } + } - if (!tagsAction.isEmpty() && !exceptedTagsAction.isEmpty()) { - // TODO check tag value? - if (exceptedTagsAction.get(tag) == null) { - return tagsAction.get(tag); - } - return null; - } - return actionByDefault; - } - return null; - } + @Override + public ActionItem getAction(Attributes dcm, Attributes dcmCopy, int tag, HMAC hmac) { + if (TagUtils.isPrivateGroup(tag)) { + if (!tagsAction.isEmpty() && exceptedTagsAction.isEmpty()) { + return tagsAction.get(tag); + } - public void profileValidation() throws Exception { - if (action == null) { - throw new Exception("Cannot build the profile " + codeName + ": Unknown Action"); - } + if (tagsAction.isEmpty() && !exceptedTagsAction.isEmpty()) { + if (exceptedTagsAction.get(tag) != null) { + return null; + } + } + + if (!tagsAction.isEmpty() && !exceptedTagsAction.isEmpty()) { + // TODO check tag value? + if (exceptedTagsAction.get(tag) == null) { + return tagsAction.get(tag); + } + return null; + } + return actionByDefault; + } + return null; + } + + public void profileValidation() throws Exception { + if (action == null) { + throw new Exception("Cannot build the profile " + codeName + ": Unknown Action"); + } + + final ExpressionError expressionError = ExpressionResult.isValid(condition, new ExprCondition(new Attributes()), + Boolean.class); + if (condition != null && !expressionError.isValid()) { + throw new Exception(expressionError.getMsg()); + } + } - final ExpressionError expressionError = - ExpressionResult.isValid(condition, new ExprCondition(new Attributes()), Boolean.class); - if (condition != null && !expressionError.isValid()) { - throw new Exception(expressionError.getMsg()); - } - } } diff --git a/src/main/java/org/karnak/backend/model/profiles/ProfileItem.java b/src/main/java/org/karnak/backend/model/profiles/ProfileItem.java index 191012f59..5661fd48a 100644 --- a/src/main/java/org/karnak/backend/model/profiles/ProfileItem.java +++ b/src/main/java/org/karnak/backend/model/profiles/ProfileItem.java @@ -16,25 +16,27 @@ import org.karnak.backend.model.profilepipe.HMAC; public interface ProfileItem { - ActionItem getAction(Attributes dcm, Attributes dcmCopy, int tag, HMAC hmac); - ActionItem put(int tag, ActionItem action); + ActionItem getAction(Attributes dcm, Attributes dcmCopy, int tag, HMAC hmac); - ActionItem remove(int tag); + ActionItem put(int tag, ActionItem action); - void clearTagMap(); + ActionItem remove(int tag); - String getName(); + void clearTagMap(); - String getCodeName(); + String getName(); - String getCondition(); + String getCodeName(); - String getOption(); + String getCondition(); - List getArguments(); + String getOption(); - Integer getPosition(); + List getArguments(); + + Integer getPosition(); + + void profileValidation() throws Exception; - void profileValidation() throws Exception; } diff --git a/src/main/java/org/karnak/backend/model/profiles/UpdateUIDsProfile.java b/src/main/java/org/karnak/backend/model/profiles/UpdateUIDsProfile.java index 49344057f..7aab2c4ed 100644 --- a/src/main/java/org/karnak/backend/model/profiles/UpdateUIDsProfile.java +++ b/src/main/java/org/karnak/backend/model/profiles/UpdateUIDsProfile.java @@ -19,22 +19,21 @@ public class UpdateUIDsProfile extends AbstractProfileItem { - public UpdateUIDsProfile(ProfileElementEntity profileElementEntity) { - super(profileElementEntity); - } + public UpdateUIDsProfile(ProfileElementEntity profileElementEntity) { + super(profileElementEntity); + } - @Override - public ActionItem getAction(Attributes dcm, Attributes dcmCopy, int tag, HMAC hmac) { - return tagMap.get(tag); - } + @Override + public ActionItem getAction(Attributes dcm, Attributes dcmCopy, int tag, HMAC hmac) { + return tagMap.get(tag); + } + + @Override + public ActionItem put(int tag, ActionItem action) { + if (!(action instanceof UID) && !(action instanceof Remove) && !(action instanceof ReplaceNull)) { + throw new IllegalStateException(String.format("The action %s is not consistent !", action)); + } + return tagMap.put(tag, action); + } - @Override - public ActionItem put(int tag, ActionItem action) { - if (!(action instanceof UID) - && !(action instanceof Remove) - && !(action instanceof ReplaceNull)) { - throw new IllegalStateException(String.format("The action %s is not consistent !", action)); - } - return tagMap.put(tag, action); - } } diff --git a/src/main/java/org/karnak/backend/model/standard/AttributeDetail.java b/src/main/java/org/karnak/backend/model/standard/AttributeDetail.java index f24cd7c00..27562887b 100644 --- a/src/main/java/org/karnak/backend/model/standard/AttributeDetail.java +++ b/src/main/java/org/karnak/backend/model/standard/AttributeDetail.java @@ -10,56 +10,58 @@ package org.karnak.backend.model.standard; public class AttributeDetail { - private final String id; - private final String keyword; - private final String name; - private final String retired; - private final String tag; - private final String valueMultiplicity; - private final String valueRepresentation; - - public AttributeDetail( - String id, - String keyword, - String name, - String retired, - String tag, - String valueMultiplicity, - String valueRepresentation) { - this.id = id; - this.keyword = keyword; - this.name = name; - this.retired = retired; - this.tag = tag; - this.valueMultiplicity = valueMultiplicity; - this.valueRepresentation = valueRepresentation; - } - - public String getId() { - return id; - } - - public String getKeyword() { - return keyword; - } - - public String getName() { - return name; - } - - public String getRetired() { - return retired; - } - - public String getTag() { - return tag; - } - - public String getValueMultiplicity() { - return valueMultiplicity; - } - - public String getValueRepresentation() { - return valueRepresentation; - } + + private final String id; + + private final String keyword; + + private final String name; + + private final String retired; + + private final String tag; + + private final String valueMultiplicity; + + private final String valueRepresentation; + + public AttributeDetail(String id, String keyword, String name, String retired, String tag, String valueMultiplicity, + String valueRepresentation) { + this.id = id; + this.keyword = keyword; + this.name = name; + this.retired = retired; + this.tag = tag; + this.valueMultiplicity = valueMultiplicity; + this.valueRepresentation = valueRepresentation; + } + + public String getId() { + return id; + } + + public String getKeyword() { + return keyword; + } + + public String getName() { + return name; + } + + public String getRetired() { + return retired; + } + + public String getTag() { + return tag; + } + + public String getValueMultiplicity() { + return valueMultiplicity; + } + + public String getValueRepresentation() { + return valueRepresentation; + } + } diff --git a/src/main/java/org/karnak/backend/model/standard/AttributeDetails.java b/src/main/java/org/karnak/backend/model/standard/AttributeDetails.java index 42249a9dc..fa534ecea 100644 --- a/src/main/java/org/karnak/backend/model/standard/AttributeDetails.java +++ b/src/main/java/org/karnak/backend/model/standard/AttributeDetails.java @@ -17,41 +17,36 @@ import org.karnak.backend.model.dicominnolitics.jsonAttributes; public class AttributeDetails { - private final Map hmapAttributeDetail; - - public AttributeDetails() { - hmapAttributeDetail = initializeAttributes(StandardAttributes.readJsonAttributes()); - } - - private Map initializeAttributes(jsonAttributes[] attributes) { - Map hmapAttribute = new HashMap<>(); - - for (jsonAttributes attribute : attributes) { - AttributeDetail attributeDetail = - new AttributeDetail( - attribute.getId(), - attribute.getKeyword(), - attribute.getName(), - attribute.getRetired(), - attribute.getTag(), - attribute.getValueMultiplicity(), - attribute.getValueRepresentation()); - - String attributeKey = attributeDetail.getId(); - hmapAttribute.put(attributeKey, attributeDetail); - } - - return hmapAttribute; - } - - public AttributeDetail getAttributeDetail(String id) { - return hmapAttributeDetail.get(id); - } - - public List getListAttributeDetail(List listId) { - return hmapAttributeDetail.entrySet().stream() - .filter(attributeDetail -> listId.contains(attributeDetail.getKey())) - .map(attributeDetail -> attributeDetail.getValue()) - .collect(Collectors.toList()); - } + + private final Map hmapAttributeDetail; + + public AttributeDetails() { + hmapAttributeDetail = initializeAttributes(StandardAttributes.readJsonAttributes()); + } + + private Map initializeAttributes(jsonAttributes[] attributes) { + Map hmapAttribute = new HashMap<>(); + + for (jsonAttributes attribute : attributes) { + AttributeDetail attributeDetail = new AttributeDetail(attribute.getId(), attribute.getKeyword(), + attribute.getName(), attribute.getRetired(), attribute.getTag(), attribute.getValueMultiplicity(), + attribute.getValueRepresentation()); + + String attributeKey = attributeDetail.getId(); + hmapAttribute.put(attributeKey, attributeDetail); + } + + return hmapAttribute; + } + + public AttributeDetail getAttributeDetail(String id) { + return hmapAttributeDetail.get(id); + } + + public List getListAttributeDetail(List listId) { + return hmapAttributeDetail.entrySet().stream() + .filter(attributeDetail -> listId.contains(attributeDetail.getKey())) + .map(attributeDetail -> attributeDetail.getValue()).collect(Collectors.toList()); + } + } diff --git a/src/main/java/org/karnak/backend/model/standard/ConfidentialityProfiles.java b/src/main/java/org/karnak/backend/model/standard/ConfidentialityProfiles.java index a158a0b24..1f4049a6f 100644 --- a/src/main/java/org/karnak/backend/model/standard/ConfidentialityProfiles.java +++ b/src/main/java/org/karnak/backend/model/standard/ConfidentialityProfiles.java @@ -26,54 +26,50 @@ public class ConfidentialityProfiles { - private static final Logger LOGGER = LoggerFactory.getLogger(ConfidentialityProfiles.class); + private static final Logger LOGGER = LoggerFactory.getLogger(ConfidentialityProfiles.class); - private final TagActionMap actionMap = new TagActionMap(); - private final List listProfiles = new ArrayList<>(); + private final TagActionMap actionMap = new TagActionMap(); - public ConfidentialityProfiles() { - final StandardConfidentialityProfiles standardConfidentialityProfiles = - new StandardConfidentialityProfiles(); - jsonConfidentialityProfiles[] confidentialityProfiles = - StandardConfidentialityProfiles.getConfidentialityProfiles(); + private final List listProfiles = new ArrayList<>(); - for (jsonConfidentialityProfiles confidentialityProfilesTag : confidentialityProfiles) { - String tag = confidentialityProfilesTag.getTag(); - ActionItem action = confidentialityProfilesTag.getBasicProfile(); - String name = confidentialityProfilesTag.getName(); - AbstractProfileItem item; - if (PrivateTagPattern.TAG_PATTERN.equals(tag)) { - try { - final ProfileElementEntity profileElementEntity = - new ProfileElementEntity( - name, - ProfileItemType.ACTION_PRIVATETAGS.getClassAlias(), - null, - "X", - null, - null, - null); - item = new PrivateTags(profileElementEntity); - } catch (Exception e) { - item = null; - LOGGER.error("Cannot build the profile: PrivateTags", e); - } - } else { - actionMap.put(tag, action); - item = null; - } + public ConfidentialityProfiles() { + final StandardConfidentialityProfiles standardConfidentialityProfiles = new StandardConfidentialityProfiles(); + jsonConfidentialityProfiles[] confidentialityProfiles = StandardConfidentialityProfiles + .getConfidentialityProfiles(); - if (item != null) { - listProfiles.add(item); - } - } - } + for (jsonConfidentialityProfiles confidentialityProfilesTag : confidentialityProfiles) { + String tag = confidentialityProfilesTag.getTag(); + ActionItem action = confidentialityProfilesTag.getBasicProfile(); + String name = confidentialityProfilesTag.getName(); + AbstractProfileItem item; + if (PrivateTagPattern.TAG_PATTERN.equals(tag)) { + try { + final ProfileElementEntity profileElementEntity = new ProfileElementEntity(name, + ProfileItemType.ACTION_PRIVATETAGS.getClassAlias(), null, "X", null, null, null); + item = new PrivateTags(profileElementEntity); + } + catch (Exception e) { + item = null; + LOGGER.error("Cannot build the profile: PrivateTags", e); + } + } + else { + actionMap.put(tag, action); + item = null; + } - public TagActionMap getActionMap() { - return actionMap; - } + if (item != null) { + listProfiles.add(item); + } + } + } + + public TagActionMap getActionMap() { + return actionMap; + } + + public List getListProfiles() { + return listProfiles; + } - public List getListProfiles() { - return listProfiles; - } } diff --git a/src/main/java/org/karnak/backend/model/standard/DICOMType.java b/src/main/java/org/karnak/backend/model/standard/DICOMType.java index e818231f6..8e76521f5 100644 --- a/src/main/java/org/karnak/backend/model/standard/DICOMType.java +++ b/src/main/java/org/karnak/backend/model/standard/DICOMType.java @@ -19,30 +19,33 @@ import org.slf4j.LoggerFactory; public class DICOMType { - private static final Logger LOGGER = LoggerFactory.getLogger(DICOMType.class); - public static String getBySOP(Attributes dcm, int tag) { - final StandardDICOM standardDICOM = AppConfig.getInstance().getStandardDICOM(); - final String sopUID = MetadataDICOMObject.getValue(dcm, Tag.SOPClassUID); - final String tagPath = MetadataDICOMObject.getTagPath(dcm, tag); + private static final Logger LOGGER = LoggerFactory.getLogger(DICOMType.class); + + public static String getBySOP(Attributes dcm, int tag) { + final StandardDICOM standardDICOM = AppConfig.getInstance().getStandardDICOM(); + final String sopUID = MetadataDICOMObject.getValue(dcm, Tag.SOPClassUID); + final String tagPath = MetadataDICOMObject.getTagPath(dcm, tag); + + String currentType = null; + try { + List moduleAttribute = standardDICOM.getAttributesBySOP(sopUID, tagPath); + if (moduleAttribute.size() == 1) { + currentType = moduleAttribute.get(0).getType(); + } + else if (moduleAttribute.size() > 1) { + currentType = ModuleAttribute.getStrictedType(moduleAttribute); + } + else { + LOGGER.warn(String.format("Could not found the attribute %s in the SOP %s.", tagPath, sopUID)); + } + } + catch (StandardDICOMException standardDICOMException) { + LOGGER.error( + String.format("Could not find a DICOM type with the SOP %s and the attribute %s", sopUID, tagPath), + standardDICOMException); + } + return currentType; + } - String currentType = null; - try { - List moduleAttribute = standardDICOM.getAttributesBySOP(sopUID, tagPath); - if (moduleAttribute.size() == 1) { - currentType = moduleAttribute.get(0).getType(); - } else if (moduleAttribute.size() > 1) { - currentType = ModuleAttribute.getStrictedType(moduleAttribute); - } else { - LOGGER.warn( - String.format("Could not found the attribute %s in the SOP %s.", tagPath, sopUID)); - } - } catch (StandardDICOMException standardDICOMException) { - LOGGER.error( - String.format( - "Could not find a DICOM type with the SOP %s and the attribute %s", sopUID, tagPath), - standardDICOMException); - } - return currentType; - } } diff --git a/src/main/java/org/karnak/backend/model/standard/Module.java b/src/main/java/org/karnak/backend/model/standard/Module.java index 690ea7985..61ede90a5 100644 --- a/src/main/java/org/karnak/backend/model/standard/Module.java +++ b/src/main/java/org/karnak/backend/model/standard/Module.java @@ -11,31 +11,34 @@ public class Module { - public static final String MANDATORY = "M"; + public static final String MANDATORY = "M"; - private final String id; - private final String usage; - private final String informationEntity; + private final String id; - public Module(String id, String usage, String informationEntity) { - this.id = id; - this.usage = usage; - this.informationEntity = informationEntity; - } + private final String usage; - public String getId() { - return id; - } + private final String informationEntity; - public static boolean moduleIsMandatory(Module module) { - return module.getUsage().equals(MANDATORY); - } + public Module(String id, String usage, String informationEntity) { + this.id = id; + this.usage = usage; + this.informationEntity = informationEntity; + } - public String getUsage() { - return usage; - } + public String getId() { + return id; + } + + public static boolean moduleIsMandatory(Module module) { + return module.getUsage().equals(MANDATORY); + } + + public String getUsage() { + return usage; + } + + public String getInformationEntity() { + return informationEntity; + } - public String getInformationEntity() { - return informationEntity; - } } diff --git a/src/main/java/org/karnak/backend/model/standard/ModuleAttribute.java b/src/main/java/org/karnak/backend/model/standard/ModuleAttribute.java index d1531304d..2c621361f 100644 --- a/src/main/java/org/karnak/backend/model/standard/ModuleAttribute.java +++ b/src/main/java/org/karnak/backend/model/standard/ModuleAttribute.java @@ -16,51 +16,53 @@ public class ModuleAttribute { - private static final List strictedTypes = Arrays.asList("1", "1C", "2", "2C", "3"); - private final String moduleTagPath; - private final String tagPath; - private final String type; - private final String moduleId; - - public ModuleAttribute(String moduleTagPath, String type, String moduleId) { - this.moduleTagPath = moduleTagPath; - this.type = type; - this.moduleId = moduleId; - this.tagPath = generateTagPath(moduleTagPath, moduleId); - } - - public static String getStrictedType(List moduleAttributes) { - for (String strictedType : strictedTypes) { - if (moduleAttributes.stream().anyMatch(attribute -> strictedType.equals(attribute.getType())) - == true) { - return strictedType; - } - } - return null; - } - - private String generateTagPath(String tagPath, String moduleId) { - List tagPathFiltered = - Arrays.stream(tagPath.split(":")) - .filter(value -> !value.equals(moduleId)) - .collect(Collectors.toList()); - - return StringUtils.join(tagPathFiltered, ":"); - } - - public String getModuleTagPath() { - return moduleTagPath; - } - - public String getTagPath() { - return tagPath; - } - - public String getType() { - return type; - } - - public String getModuleId() { - return moduleId; - } + private static final List strictedTypes = Arrays.asList("1", "1C", "2", "2C", "3"); + + private final String moduleTagPath; + + private final String tagPath; + + private final String type; + + private final String moduleId; + + public ModuleAttribute(String moduleTagPath, String type, String moduleId) { + this.moduleTagPath = moduleTagPath; + this.type = type; + this.moduleId = moduleId; + this.tagPath = generateTagPath(moduleTagPath, moduleId); + } + + public static String getStrictedType(List moduleAttributes) { + for (String strictedType : strictedTypes) { + if (moduleAttributes.stream().anyMatch(attribute -> strictedType.equals(attribute.getType())) == true) { + return strictedType; + } + } + return null; + } + + private String generateTagPath(String tagPath, String moduleId) { + List tagPathFiltered = Arrays.stream(tagPath.split(":")).filter(value -> !value.equals(moduleId)) + .collect(Collectors.toList()); + + return StringUtils.join(tagPathFiltered, ":"); + } + + public String getModuleTagPath() { + return moduleTagPath; + } + + public String getTagPath() { + return tagPath; + } + + public String getType() { + return type; + } + + public String getModuleId() { + return moduleId; + } + } diff --git a/src/main/java/org/karnak/backend/model/standard/ModuleToAttributes.java b/src/main/java/org/karnak/backend/model/standard/ModuleToAttributes.java index 84e7afd01..4854b4104 100644 --- a/src/main/java/org/karnak/backend/model/standard/ModuleToAttributes.java +++ b/src/main/java/org/karnak/backend/model/standard/ModuleToAttributes.java @@ -18,50 +18,45 @@ public class ModuleToAttributes { - /* - * > - * */ - private final Map> HMapModuleAttributes; + /* + * > + */ + private final Map> HMapModuleAttributes; + + public ModuleToAttributes() { + HMapModuleAttributes = initializeAttributes(StandardModuleToAttributes.readJsonModuleToAttributes()); + } + + private Map> initializeAttributes(jsonModuleToAttribute[] moduleToAttributes) { + Map> HMapModuleAttributes = new HashMap<>(); + + for (jsonModuleToAttribute moduleToAttribute : moduleToAttributes) { + ModuleAttribute moduleAttribute = new ModuleAttribute(moduleToAttribute.getPath(), + moduleToAttribute.getType(), moduleToAttribute.getModuleId()); + + String moduleKey = moduleToAttribute.getModuleId(); + if (!HMapModuleAttributes.containsKey(moduleKey)) { + HMapModuleAttributes.put(moduleKey, new HashMap<>()); + } + HMapModuleAttributes.get(moduleKey).put(moduleAttribute.getTagPath(), moduleAttribute); + } + + return HMapModuleAttributes; + } + + public Map getAttributesByModule(String moduleID) { + return HMapModuleAttributes.get(moduleID); + } + + public Map getModuleAttributesByType(String moduleID, String type) + throws ModuleNotFoundException { + Map attributes = HMapModuleAttributes.get(moduleID); + if (attributes == null) { + throw new ModuleNotFoundException( + String.format("Unable to get module attributes. Could not find the module %s", moduleID)); + } + return attributes.entrySet().stream().filter(entry -> type.equals(entry.getValue().getType())) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + } - public ModuleToAttributes() { - HMapModuleAttributes = - initializeAttributes(StandardModuleToAttributes.readJsonModuleToAttributes()); - } - - private Map> initializeAttributes( - jsonModuleToAttribute[] moduleToAttributes) { - Map> HMapModuleAttributes = new HashMap<>(); - - for (jsonModuleToAttribute moduleToAttribute : moduleToAttributes) { - ModuleAttribute moduleAttribute = - new ModuleAttribute( - moduleToAttribute.getPath(), - moduleToAttribute.getType(), - moduleToAttribute.getModuleId()); - - String moduleKey = moduleToAttribute.getModuleId(); - if (!HMapModuleAttributes.containsKey(moduleKey)) { - HMapModuleAttributes.put(moduleKey, new HashMap<>()); - } - HMapModuleAttributes.get(moduleKey).put(moduleAttribute.getTagPath(), moduleAttribute); - } - - return HMapModuleAttributes; - } - - public Map getAttributesByModule(String moduleID) { - return HMapModuleAttributes.get(moduleID); - } - - public Map getModuleAttributesByType(String moduleID, String type) - throws ModuleNotFoundException { - Map attributes = HMapModuleAttributes.get(moduleID); - if (attributes == null) { - throw new ModuleNotFoundException( - String.format("Unable to get module attributes. Could not find the module %s", moduleID)); - } - return attributes.entrySet().stream() - .filter(entry -> type.equals(entry.getValue().getType())) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - } } diff --git a/src/main/java/org/karnak/backend/model/standard/SOP.java b/src/main/java/org/karnak/backend/model/standard/SOP.java index 2ea43c864..97a423ad7 100644 --- a/src/main/java/org/karnak/backend/model/standard/SOP.java +++ b/src/main/java/org/karnak/backend/model/standard/SOP.java @@ -13,37 +13,42 @@ public class SOP { - private final String UID; - private final String name; - private final String ciod; - private final String ciod_id; - private final ArrayList modules; - - SOP(String UID, String name, String ciod, String ciod_id, ArrayList modules) { - this.UID = UID; - this.name = name; - this.ciod = ciod; - this.ciod_id = ciod_id; - this.modules = modules; - } - - public String getUID() { - return UID; - } - - public String getName() { - return name; - } - - public String getCiod() { - return ciod; - } - - public String getCiod_id() { - return ciod_id; - } - - public ArrayList getModules() { - return modules; - } + private final String UID; + + private final String name; + + private final String ciod; + + private final String ciod_id; + + private final ArrayList modules; + + SOP(String UID, String name, String ciod, String ciod_id, ArrayList modules) { + this.UID = UID; + this.name = name; + this.ciod = ciod; + this.ciod_id = ciod_id; + this.modules = modules; + } + + public String getUID() { + return UID; + } + + public String getName() { + return name; + } + + public String getCiod() { + return ciod; + } + + public String getCiod_id() { + return ciod_id; + } + + public ArrayList getModules() { + return modules; + } + } diff --git a/src/main/java/org/karnak/backend/model/standard/SOPS.java b/src/main/java/org/karnak/backend/model/standard/SOPS.java index f15a517e5..1508d7f94 100644 --- a/src/main/java/org/karnak/backend/model/standard/SOPS.java +++ b/src/main/java/org/karnak/backend/model/standard/SOPS.java @@ -26,150 +26,136 @@ public class SOPS { - private static HashMap HMapSOPS; - - public SOPS() { - HashMap mapCIODS = initializeCIODS(StandardCIODS.readJsonCIODS()); - HashMap> mapCIODModules = - initializeHMapCIODModules(StandardCIODtoModules.readJsonCIODToModules()); - HMapSOPS = initializeSOPS(StandardSOPS.readJsonSOPS(), mapCIODS, mapCIODModules); - } - - private HashMap initializeSOPS( - jsonSOP[] sops, - HashMap mapCIODS, - HashMap> mapCIODModules) { - HashMap mapSOPS = new HashMap<>(); - for (jsonSOP sop : sops) { - String ciodId = mapCIODS.get(sop.getCiod()); - ArrayList modules = mapCIODModules.get(ciodId); - SOP newSOP = new SOP(sop.getId(), sop.getName(), sop.getCiod(), ciodId, modules); - mapSOPS.put(sop.getId(), newSOP); - } - return mapSOPS; - } - - private HashMap initializeCIODS(jsonCIOD[] ciods) { - HashMap mapCIODS = new HashMap<>(); - for (jsonCIOD ciod : ciods) { - mapCIODS.put(ciod.getName(), ciod.getId()); - } - return mapCIODS; - } - - private HashMap> initializeHMapCIODModules( - jsonCIODtoModule[] ciodToModules) { - HashMap> mapCIODModules = new HashMap<>(); - - for (jsonCIODtoModule ciodToModule : ciodToModules) { - String ciodId = ciodToModule.getCiodId(); - Module module = - new Module( - ciodToModule.getModuleId(), - ciodToModule.getUsage(), - ciodToModule.getInformationEntity()); - if (mapCIODModules.containsKey(ciodId)) { - ArrayList modules = mapCIODModules.get(ciodId); - modules.add(module); - } else { - ArrayList modules = new ArrayList<>(); - modules.add(module); - mapCIODModules.put(ciodId, modules); - } - } - return mapCIODModules; - } - - public List getAllUIDs() { - return new ArrayList<>(HMapSOPS.keySet()); - } - - public SOP getSOP(String uid) { - return HMapSOPS.get(uid); - } - - public String getName(String uid) throws SOPNotFoundException { - SOP sop = HMapSOPS.get(uid); - if (sop == null) { - throw new SOPNotFoundException( - String.format("Unable to get name. Could not find the SOP UID %s", uid)); - } - return sop.getName(); - } - - public String getCIOD(String uid) throws SOPNotFoundException { - SOP sop = HMapSOPS.get(uid); - if (sop == null) { - throw new SOPNotFoundException( - String.format("Unable to get CIOD. Could not find the SOP UID %s", uid)); - } - return sop.getCiod(); - } - - public String getIdCIOD(String uid) throws SOPNotFoundException { - SOP sop = HMapSOPS.get(uid); - if (sop == null) { - throw new SOPNotFoundException( - String.format("Unable to get ID CIOD. Could not find the SOP UID %s", uid)); - } - return sop.getCiod_id(); - } - - public Optional getModuleByModuleID(String uid, String moduleId) - throws SOPNotFoundException { - SOP sop = HMapSOPS.get(uid); - if (sop == null) { - throw new SOPNotFoundException( - String.format( - "Unable to get if module %s is present. Could not find the SOP UID %s", - moduleId, uid)); - } - return sop.getModules().stream().filter(module -> moduleId.equals(module.getId())).findFirst(); - } - - public List getSopModules(String uid) throws SOPNotFoundException { - SOP sop = HMapSOPS.get(uid); - if (sop == null) { - throw new SOPNotFoundException( - String.format("Unable to get SOP modules. Could not find the SOP UID %s", uid)); - } - return sop.getModules(); - } - - public List getSopModulesName(String uid) throws SOPNotFoundException { - SOP sop = HMapSOPS.get(uid); - if (sop == null) { - throw new SOPNotFoundException( - String.format("Unable to get SOP modules name. Could not find the SOP UID %s", uid)); - } - return sop.getModules().stream().map(Module::getId).collect(Collectors.toList()); - } - - public Boolean moduleIsPresent(String uid, String moduleId) throws SOPNotFoundException { - SOP sop = HMapSOPS.get(uid); - if (sop == null) { - throw new SOPNotFoundException( - String.format( - "Unable to get if module %s is present. Could not find the SOP UID %s", - moduleId, uid)); - } - Predicate modulePredicate = module -> moduleId.equals(module.getId()); - return sop.getModules().stream().anyMatch(modulePredicate); - } - - public Map> getModuleToAttribute( - String uid, ModuleToAttributes moduleToAttributes) throws SOPNotFoundException { - Map> mapModuleAttributes = new HashMap<>(); - try { - getSopModules(uid) - .forEach( - module -> - mapModuleAttributes.put( - module, moduleToAttributes.getAttributesByModule(module.getId()))); - } catch (SOPNotFoundException sopNotFoundException) { - throw new SOPNotFoundException( - String.format("Unable to get module attributes. Could not find the SOP UID %s", uid)); - } - return mapModuleAttributes; - } + private static HashMap HMapSOPS; + + public SOPS() { + HashMap mapCIODS = initializeCIODS(StandardCIODS.readJsonCIODS()); + HashMap> mapCIODModules = initializeHMapCIODModules( + StandardCIODtoModules.readJsonCIODToModules()); + HMapSOPS = initializeSOPS(StandardSOPS.readJsonSOPS(), mapCIODS, mapCIODModules); + } + + private HashMap initializeSOPS(jsonSOP[] sops, HashMap mapCIODS, + HashMap> mapCIODModules) { + HashMap mapSOPS = new HashMap<>(); + for (jsonSOP sop : sops) { + String ciodId = mapCIODS.get(sop.getCiod()); + ArrayList modules = mapCIODModules.get(ciodId); + SOP newSOP = new SOP(sop.getId(), sop.getName(), sop.getCiod(), ciodId, modules); + mapSOPS.put(sop.getId(), newSOP); + } + return mapSOPS; + } + + private HashMap initializeCIODS(jsonCIOD[] ciods) { + HashMap mapCIODS = new HashMap<>(); + for (jsonCIOD ciod : ciods) { + mapCIODS.put(ciod.getName(), ciod.getId()); + } + return mapCIODS; + } + + private HashMap> initializeHMapCIODModules(jsonCIODtoModule[] ciodToModules) { + HashMap> mapCIODModules = new HashMap<>(); + + for (jsonCIODtoModule ciodToModule : ciodToModules) { + String ciodId = ciodToModule.getCiodId(); + Module module = new Module(ciodToModule.getModuleId(), ciodToModule.getUsage(), + ciodToModule.getInformationEntity()); + if (mapCIODModules.containsKey(ciodId)) { + ArrayList modules = mapCIODModules.get(ciodId); + modules.add(module); + } + else { + ArrayList modules = new ArrayList<>(); + modules.add(module); + mapCIODModules.put(ciodId, modules); + } + } + return mapCIODModules; + } + + public List getAllUIDs() { + return new ArrayList<>(HMapSOPS.keySet()); + } + + public SOP getSOP(String uid) { + return HMapSOPS.get(uid); + } + + public String getName(String uid) throws SOPNotFoundException { + SOP sop = HMapSOPS.get(uid); + if (sop == null) { + throw new SOPNotFoundException(String.format("Unable to get name. Could not find the SOP UID %s", uid)); + } + return sop.getName(); + } + + public String getCIOD(String uid) throws SOPNotFoundException { + SOP sop = HMapSOPS.get(uid); + if (sop == null) { + throw new SOPNotFoundException(String.format("Unable to get CIOD. Could not find the SOP UID %s", uid)); + } + return sop.getCiod(); + } + + public String getIdCIOD(String uid) throws SOPNotFoundException { + SOP sop = HMapSOPS.get(uid); + if (sop == null) { + throw new SOPNotFoundException(String.format("Unable to get ID CIOD. Could not find the SOP UID %s", uid)); + } + return sop.getCiod_id(); + } + + public Optional getModuleByModuleID(String uid, String moduleId) throws SOPNotFoundException { + SOP sop = HMapSOPS.get(uid); + if (sop == null) { + throw new SOPNotFoundException(String + .format("Unable to get if module %s is present. Could not find the SOP UID %s", moduleId, uid)); + } + return sop.getModules().stream().filter(module -> moduleId.equals(module.getId())).findFirst(); + } + + public List getSopModules(String uid) throws SOPNotFoundException { + SOP sop = HMapSOPS.get(uid); + if (sop == null) { + throw new SOPNotFoundException( + String.format("Unable to get SOP modules. Could not find the SOP UID %s", uid)); + } + return sop.getModules(); + } + + public List getSopModulesName(String uid) throws SOPNotFoundException { + SOP sop = HMapSOPS.get(uid); + if (sop == null) { + throw new SOPNotFoundException( + String.format("Unable to get SOP modules name. Could not find the SOP UID %s", uid)); + } + return sop.getModules().stream().map(Module::getId).collect(Collectors.toList()); + } + + public Boolean moduleIsPresent(String uid, String moduleId) throws SOPNotFoundException { + SOP sop = HMapSOPS.get(uid); + if (sop == null) { + throw new SOPNotFoundException(String + .format("Unable to get if module %s is present. Could not find the SOP UID %s", moduleId, uid)); + } + Predicate modulePredicate = module -> moduleId.equals(module.getId()); + return sop.getModules().stream().anyMatch(modulePredicate); + } + + public Map> getModuleToAttribute(String uid, + ModuleToAttributes moduleToAttributes) throws SOPNotFoundException { + Map> mapModuleAttributes = new HashMap<>(); + try { + getSopModules(uid).forEach(module -> mapModuleAttributes.put(module, + moduleToAttributes.getAttributesByModule(module.getId()))); + } + catch (SOPNotFoundException sopNotFoundException) { + throw new SOPNotFoundException( + String.format("Unable to get module attributes. Could not find the SOP UID %s", uid)); + } + return mapModuleAttributes; + } + } diff --git a/src/main/java/org/karnak/backend/model/standard/StandardDICOM.java b/src/main/java/org/karnak/backend/model/standard/StandardDICOM.java index 7cfee9ecc..994c9be9d 100644 --- a/src/main/java/org/karnak/backend/model/standard/StandardDICOM.java +++ b/src/main/java/org/karnak/backend/model/standard/StandardDICOM.java @@ -19,88 +19,86 @@ public class StandardDICOM { - private final SOPS sops; - private final ModuleToAttributes moduleToAttributes; - private final AttributeDetails attributeDetails; - - public StandardDICOM() { - sops = new SOPS(); - moduleToAttributes = new ModuleToAttributes(); - attributeDetails = new AttributeDetails(); - } - - public static String cleanTagPath(String tagPath) { - return tagPath.replaceAll("[(),]", "").toLowerCase(); - } - - public List getAllSOPuids() { - return sops.getAllUIDs(); - } - - public String getCIOD(String sopUID) throws SOPNotFoundException { - return sops.getCIOD(sopUID); - } - - public String getIdCIOD(String sopUID) throws SOPNotFoundException { - return sops.getIdCIOD(sopUID); - } - - public Optional getModuleByModuleID(String sopUID, String moduleId) - throws SOPNotFoundException { - return sops.getModuleByModuleID(sopUID, moduleId); - } - - public boolean moduleIsPresent(String sopUID, String moduleId) throws SOPNotFoundException { - return sops.moduleIsPresent(sopUID, moduleId); - } - - public Map> getModulesBySOP(String sopUID) - throws SOPNotFoundException { - return sops.getModuleToAttribute(sopUID, moduleToAttributes); - } - - public List getModulesNameBySOP(String sopUID) throws SOPNotFoundException { - return sops.getSopModulesName(sopUID); - } - - public List getAttributesBySOP(String sopUID, int tagPath) - throws SOPNotFoundException { - return getAttributesBySOP(sopUID, TagUtils.toHexString(tagPath)); - } - - public List getAttributesBySOP(String sopUID, String tagPath) - throws SOPNotFoundException { - String tagPathCleaned = cleanTagPath(tagPath); - Map> mapModuleAttributes = getModulesBySOP(sopUID); - List moduleAttributes = new ArrayList<>(); - mapModuleAttributes.forEach( - (module, attr) -> { - ModuleAttribute moduleAttribute = attr.get(tagPathCleaned); - if (moduleAttribute != null) { - moduleAttributes.add(moduleAttribute); - } - }); - return moduleAttributes; - } - - public Map getAttributesByModule(String moduleId) { - return moduleToAttributes.getAttributesByModule(moduleId); - } - - public List getAttributeListByModule(String moduleId) { - return new ArrayList<>(moduleToAttributes.getAttributesByModule(moduleId).values()); - } - - public Map getModuleAttributesByType(String moduleId, String type) - throws ModuleNotFoundException { - return moduleToAttributes.getModuleAttributesByType(moduleId, type); - } - - public AttributeDetail getAttributeDetail(String tag) { - return attributeDetails.getAttributeDetail(tag); - } - - public List getListAttributeDetail(List tag) { - return attributeDetails.getListAttributeDetail(tag); - } + private final SOPS sops; + + private final ModuleToAttributes moduleToAttributes; + + private final AttributeDetails attributeDetails; + + public StandardDICOM() { + sops = new SOPS(); + moduleToAttributes = new ModuleToAttributes(); + attributeDetails = new AttributeDetails(); + } + + public static String cleanTagPath(String tagPath) { + return tagPath.replaceAll("[(),]", "").toLowerCase(); + } + + public List getAllSOPuids() { + return sops.getAllUIDs(); + } + + public String getCIOD(String sopUID) throws SOPNotFoundException { + return sops.getCIOD(sopUID); + } + + public String getIdCIOD(String sopUID) throws SOPNotFoundException { + return sops.getIdCIOD(sopUID); + } + + public Optional getModuleByModuleID(String sopUID, String moduleId) throws SOPNotFoundException { + return sops.getModuleByModuleID(sopUID, moduleId); + } + + public boolean moduleIsPresent(String sopUID, String moduleId) throws SOPNotFoundException { + return sops.moduleIsPresent(sopUID, moduleId); + } + + public Map> getModulesBySOP(String sopUID) throws SOPNotFoundException { + return sops.getModuleToAttribute(sopUID, moduleToAttributes); + } + + public List getModulesNameBySOP(String sopUID) throws SOPNotFoundException { + return sops.getSopModulesName(sopUID); + } + + public List getAttributesBySOP(String sopUID, int tagPath) throws SOPNotFoundException { + return getAttributesBySOP(sopUID, TagUtils.toHexString(tagPath)); + } + + public List getAttributesBySOP(String sopUID, String tagPath) throws SOPNotFoundException { + String tagPathCleaned = cleanTagPath(tagPath); + Map> mapModuleAttributes = getModulesBySOP(sopUID); + List moduleAttributes = new ArrayList<>(); + mapModuleAttributes.forEach((module, attr) -> { + ModuleAttribute moduleAttribute = attr.get(tagPathCleaned); + if (moduleAttribute != null) { + moduleAttributes.add(moduleAttribute); + } + }); + return moduleAttributes; + } + + public Map getAttributesByModule(String moduleId) { + return moduleToAttributes.getAttributesByModule(moduleId); + } + + public List getAttributeListByModule(String moduleId) { + return new ArrayList<>(moduleToAttributes.getAttributesByModule(moduleId).values()); + } + + public Map getModuleAttributesByType(String moduleId, String type) + throws ModuleNotFoundException { + return moduleToAttributes.getModuleAttributesByType(moduleId, type); + } + + public AttributeDetail getAttributeDetail(String tag) { + return attributeDetails.getAttributeDetail(tag); + } + + public List getListAttributeDetail(List tag) { + return attributeDetails.getListAttributeDetail(tag); + } + } diff --git a/src/main/java/org/karnak/backend/security/DefaultIdpLoadCondition.java b/src/main/java/org/karnak/backend/security/DefaultIdpLoadCondition.java index 0fb1c5f2e..3b7b357c1 100644 --- a/src/main/java/org/karnak/backend/security/DefaultIdpLoadCondition.java +++ b/src/main/java/org/karnak/backend/security/DefaultIdpLoadCondition.java @@ -17,16 +17,16 @@ import org.springframework.core.type.AnnotatedTypeMetadata; /** - * Default behaviour to load the IDP If property IDP is missing or different from oidc: load the in - * memory IDP + * Default behaviour to load the IDP If property IDP is missing or different from oidc: + * load the in memory IDP */ public class DefaultIdpLoadCondition implements Condition { - @Override - public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { - // Define default IDP - return !Objects.equals( - context.getEnvironment().getProperty(EnvironmentVariable.IDP.getCode()), - ApplicationProfile.OIDC.getCode()); - } + @Override + public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { + // Define default IDP + return !Objects.equals(context.getEnvironment().getProperty(EnvironmentVariable.IDP.getCode()), + ApplicationProfile.OIDC.getCode()); + } + } diff --git a/src/main/java/org/karnak/backend/security/OpenIdConnectLogoutHandler.java b/src/main/java/org/karnak/backend/security/OpenIdConnectLogoutHandler.java index e67fc6325..f085b1d35 100644 --- a/src/main/java/org/karnak/backend/security/OpenIdConnectLogoutHandler.java +++ b/src/main/java/org/karnak/backend/security/OpenIdConnectLogoutHandler.java @@ -23,43 +23,39 @@ /** Handle IDP logout */ public class OpenIdConnectLogoutHandler extends SecurityContextLogoutHandler { - private static final Logger logger = LoggerFactory.getLogger(OpenIdConnectLogoutHandler.class); + private static final Logger logger = LoggerFactory.getLogger(OpenIdConnectLogoutHandler.class); - private static final String END_SESSION_ENDPOINT = "/protocol/openid-connect/logout"; - private static final String ID_TOKEN_HINT = "id_token_hint"; + private static final String END_SESSION_ENDPOINT = "/protocol/openid-connect/logout"; - @Override - public void logout( - HttpServletRequest request, HttpServletResponse response, Authentication authentication) { - // Security context logout - super.logout(request, response, authentication); + private static final String ID_TOKEN_HINT = "id_token_hint"; - if (authentication != null && authentication.getPrincipal() instanceof OidcUser) { - // Idp logout - propagateLogoutToIdp((OidcUser) authentication.getPrincipal()); - } - } + @Override + public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { + // Security context logout + super.logout(request, response, authentication); - /** - * Propagate logout to IDP - * - * @param user OpenId Connect user - */ - private void propagateLogoutToIdp(OidcUser user) { - RestTemplate restTemplate = new RestTemplate(); + if (authentication != null && authentication.getPrincipal() instanceof OidcUser) { + // Idp logout + propagateLogoutToIdp((OidcUser) authentication.getPrincipal()); + } + } - // Build logout URI - String endSessionEndpoint = user.getIssuer() + END_SESSION_ENDPOINT; - UriComponentsBuilder builder = - UriComponentsBuilder.fromUriString(endSessionEndpoint) - .queryParam(ID_TOKEN_HINT, user.getIdToken().getTokenValue()); + /** + * Propagate logout to IDP + * @param user OpenId Connect user + */ + private void propagateLogoutToIdp(OidcUser user) { + RestTemplate restTemplate = new RestTemplate(); + + // Build logout URI + String endSessionEndpoint = user.getIssuer() + END_SESSION_ENDPOINT; + UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(endSessionEndpoint).queryParam(ID_TOKEN_HINT, + user.getIdToken().getTokenValue()); + + // Call IDP logout endpoint + ResponseEntity logoutResponse = restTemplate.getForEntity(builder.toUriString(), String.class); + logger.info(logoutResponse.getStatusCode().is2xxSuccessful() ? "Successful IDP logout" + : "Could not propagate logout to IDP"); + } - // Call IDP logout endpoint - ResponseEntity logoutResponse = - restTemplate.getForEntity(builder.toUriString(), String.class); - logger.info( - logoutResponse.getStatusCode().is2xxSuccessful() - ? "Successful IDP logout" - : "Could not propagate logout to IDP"); - } } diff --git a/src/main/java/org/karnak/backend/security/UIServiceInitListener.java b/src/main/java/org/karnak/backend/security/UIServiceInitListener.java index 319630b4a..1fd3e6225 100644 --- a/src/main/java/org/karnak/backend/security/UIServiceInitListener.java +++ b/src/main/java/org/karnak/backend/security/UIServiceInitListener.java @@ -32,77 +32,64 @@ @Component public class UIServiceInitListener implements VaadinServiceInitListener { - // All view classes - private final List> viewClasses = - Arrays.asList( - ForwardNodeView.class, - ProfileView.class, - ProjectView.class, - ExternalIDView.class, - MainzellisteView.class, - PseudonymMappingView.class, - DicomMainView.class, - HelpView.class); + // All view classes + private final List> viewClasses = Arrays.asList( + ForwardNodeView.class, ProfileView.class, ProjectView.class, ExternalIDView.class, MainzellisteView.class, + PseudonymMappingView.class, DicomMainView.class, HelpView.class); - /** - * Listen for the initialization of the UI (the internal root component in Vaadin) and then add a - * listener before every view transition - * - * @param event ServiceInitEvent - */ - @Override - public void serviceInit(ServiceInitEvent event) { - event - .getSource() - .addUIInitListener( - uiEvent -> { - final UI ui = uiEvent.getUI(); - ui.addBeforeEnterListener(this::beforeEnter); - }); - } + /** + * Listen for the initialization of the UI (the internal root component in Vaadin) and + * then add a listener before every view transition + * @param event ServiceInitEvent + */ + @Override + public void serviceInit(ServiceInitEvent event) { + event.getSource().addUIInitListener(uiEvent -> { + final UI ui = uiEvent.getUI(); + ui.addBeforeEnterListener(this::beforeEnter); + }); + } - /** - * Check authorized view to display to the user - * - *

If none redirect to the unauthorized view - * - * @param event BeforeEnterEvent - */ - private void beforeEnter(BeforeEnterEvent event) { - // Lofin screen in memory - boolean isLoginScreen = - Objects.equals( - event.getNavigationTarget().getName(), - "org.karnak.frontend.authentication.LoginScreen"); + /** + * Check authorized view to display to the user + * + *

+ * If none redirect to the unauthorized view + * @param event BeforeEnterEvent + */ + private void beforeEnter(BeforeEnterEvent event) { + // Lofin screen in memory + boolean isLoginScreen = Objects.equals(event.getNavigationTarget().getName(), + "org.karnak.frontend.authentication.LoginScreen"); - // Root view - boolean isForwardNode = - Objects.equals( - event.getNavigationTarget().getName(), - "org.karnak.frontend.forwardnode.ForwardNodeView"); + // Root view + boolean isForwardNode = Objects.equals(event.getNavigationTarget().getName(), + "org.karnak.frontend.forwardnode.ForwardNodeView"); - if (SecurityUtil.isUserLoggedIn() - && !SecurityUtil.isAccessGranted(event.getNavigationTarget()) - && !isLoginScreen) { - // If root requested - if (isForwardNode) { - // List all authorized views and take first one if user request root of the application - // Try to find first authorized view - Optional> - firstAuthorizedViewFoundOpt = - viewClasses.stream().filter(SecurityUtil::isAccessGranted).findFirst(); + if (SecurityUtil.isUserLoggedIn() && !SecurityUtil.isAccessGranted(event.getNavigationTarget()) + && !isLoginScreen) { + // If root requested + if (isForwardNode) { + // List all authorized views and take first one if user request root of + // the application + // Try to find first authorized view + Optional> firstAuthorizedViewFoundOpt = viewClasses + .stream().filter(SecurityUtil::isAccessGranted).findFirst(); + + // If an authorized view have been found + if (firstAuthorizedViewFoundOpt.isPresent()) { + event.rerouteTo(firstAuthorizedViewFoundOpt.get()); + } + else { + // No authorized view has been found + event.rerouteTo(NotAuthorizedScreen.class); + } + } + else { + // Case direct access not authorized + event.rerouteTo(NotAuthorizedScreen.class); + } + } + } - // If an authorized view have been found - if (firstAuthorizedViewFoundOpt.isPresent()) { - event.rerouteTo(firstAuthorizedViewFoundOpt.get()); - } else { - // No authorized view has been found - event.rerouteTo(NotAuthorizedScreen.class); - } - } else { - // Case direct access not authorized - event.rerouteTo(NotAuthorizedScreen.class); - } - } - } } diff --git a/src/main/java/org/karnak/backend/service/CStoreSCPService.java b/src/main/java/org/karnak/backend/service/CStoreSCPService.java index 08c4f6ceb..99057ebc7 100644 --- a/src/main/java/org/karnak/backend/service/CStoreSCPService.java +++ b/src/main/java/org/karnak/backend/service/CStoreSCPService.java @@ -43,154 +43,139 @@ @Service public class CStoreSCPService extends BasicCStoreSCP { - private static final Logger LOGGER = LoggerFactory.getLogger(CStoreSCPService.class); - - // Service - private final DestinationRepo destinationRepo; - private final ForwardService forwardService; - - private Map> destinations; - private volatile int priority; - private volatile int status = 0; - - // Scheduled service for updating status transfer in progress - private ScheduledFuture isDelayOver; - private final ScheduledExecutorService executorService = - Executors.newSingleThreadScheduledExecutor(); - - @Autowired - public CStoreSCPService( - final DestinationRepo destinationRepo, final ForwardService forwardService) { - super("*"); - this.destinationRepo = destinationRepo; - this.forwardService = forwardService; - } - - public void init(Map> destinations) { - this.destinations = destinations; - } - - @Override - protected void store( - Association as, PresentationContext pc, Attributes rq, PDVInputStream data, Attributes rsp) - throws IOException { - Optional sourceNode = - destinations.keySet().stream() - .filter(n -> n.getForwardAETitle().equals(as.getCalledAET())) - .findFirst(); - if (sourceNode.isEmpty()) { - throw new IllegalStateException("Cannot find the forward AeTitle " + as.getCalledAET()); - } - ForwardDicomNode fwdNode = sourceNode.get(); - List destList = destinations.get(fwdNode); - if (destList == null || destList.isEmpty()) { - throw new IllegalStateException("No DICOM destinations for " + fwdNode); - } - - DicomNode callingNode = DicomNode.buildRemoteDicomNode(as); - Set srcNodes = fwdNode.getAcceptedSourceNodes(); - boolean valid = - srcNodes.isEmpty() - || srcNodes.stream() - .anyMatch( - n -> - n.getAet().equals(callingNode.getAet()) - && (!n.isValidateHostname() - || n.equalsHostname(callingNode.getHostname()))); - if (!valid) { - rsp.setInt(Tag.Status, VR.US, Status.NotAuthorized); - LOGGER.error( - "Refused: not authorized (124H). Source node: {}. SopUID: {}", - callingNode, - rq.getString(Tag.AffectedSOPInstanceUID)); - return; - } - - rsp.setInt(Tag.Status, VR.US, status); - - try { - Params p = - new Params( - rq.getString(Tag.AffectedSOPInstanceUID), - rq.getString(Tag.AffectedSOPClassUID), - pc.getTransferSyntax(), - priority, - data, - as); - - // Update transfer status of destinations - updateTransferStatus(destList); - - forwardService.storeMultipleDestination(fwdNode, destList, p); - - } catch (Exception e) { - throw new DicomServiceException(Status.ProcessingFailure, e); - } - } - - /** - * Update transfer status: if there is a transfer in progress set status to true and schedule a - * thread which will set back status to false in a certain delay. If a transfer is still in - * progress after the end of the delay, set status to true and an other delay is scheduled. - * - * @param destinations Destinations to update - */ - private void updateTransferStatus(List destinations) { - // if delay is over or first iteration - if (isDelayOver == null || isDelayOver.isDone()) { - // Set flag transfer in progress - destinations.forEach(d -> updateTransferStatus(d, true)); - // In a certain delay set back transfer in progress to false - isDelayOver = - executorService.schedule( - () -> destinations.forEach(d -> updateTransferStatus(d, false)), 5, TimeUnit.SECONDS); - } - } - - /** - * Update the transfer status of a destination - * - * @param destination Destination to retrieve - * @param status Status to update - */ - private void updateTransferStatus(ForwardDestination destination, boolean status) { - // Retrieve the destination entity - Optional destinationEntityOptional = - destinationRepo.findById(destination.getId()); - - if (destinationEntityOptional.isPresent()) { - // Update the destination transfer status if destination has been found and destination - // is active - DestinationEntity destinationEntity = destinationEntityOptional.get(); - if (destinationEntity.isActivate()) { - destinationEntity.setTransferInProgress(status); - destinationEntity.setLastTransfer(LocalDateTime.now(ZoneId.of("CET"))); - destinationRepo.save(destinationEntity); - } - } - } - - public Map> getDestinations() { - return destinations; - } - - public void setDestinations(Map> destinations) { - this.destinations = destinations; - } - - public int getPriority() { - return priority; - } - - public void setPriority(int priority) { - this.priority = priority; - } - - public int getStatus() { - return status; - } - - public void setStatus(int status) { - this.status = status; - } + private static final Logger LOGGER = LoggerFactory.getLogger(CStoreSCPService.class); + + // Service + private final DestinationRepo destinationRepo; + + private final ForwardService forwardService; + + private Map> destinations; + + private volatile int priority; + + private volatile int status = 0; + + // Scheduled service for updating status transfer in progress + private ScheduledFuture isDelayOver; + + private final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(); + + @Autowired + public CStoreSCPService(final DestinationRepo destinationRepo, final ForwardService forwardService) { + super("*"); + this.destinationRepo = destinationRepo; + this.forwardService = forwardService; + } + + public void init(Map> destinations) { + this.destinations = destinations; + } + + @Override + protected void store(Association as, PresentationContext pc, Attributes rq, PDVInputStream data, Attributes rsp) + throws IOException { + Optional sourceNode = destinations.keySet().stream() + .filter(n -> n.getForwardAETitle().equals(as.getCalledAET())).findFirst(); + if (sourceNode.isEmpty()) { + throw new IllegalStateException("Cannot find the forward AeTitle " + as.getCalledAET()); + } + ForwardDicomNode fwdNode = sourceNode.get(); + List destList = destinations.get(fwdNode); + if (destList == null || destList.isEmpty()) { + throw new IllegalStateException("No DICOM destinations for " + fwdNode); + } + + DicomNode callingNode = DicomNode.buildRemoteDicomNode(as); + Set srcNodes = fwdNode.getAcceptedSourceNodes(); + boolean valid = srcNodes.isEmpty() || srcNodes.stream().anyMatch(n -> n.getAet().equals(callingNode.getAet()) + && (!n.isValidateHostname() || n.equalsHostname(callingNode.getHostname()))); + if (!valid) { + rsp.setInt(Tag.Status, VR.US, Status.NotAuthorized); + LOGGER.error("Refused: not authorized (124H). Source node: {}. SopUID: {}", callingNode, + rq.getString(Tag.AffectedSOPInstanceUID)); + return; + } + + rsp.setInt(Tag.Status, VR.US, status); + + try { + Params p = new Params(rq.getString(Tag.AffectedSOPInstanceUID), rq.getString(Tag.AffectedSOPClassUID), + pc.getTransferSyntax(), priority, data, as); + + // Update transfer status of destinations + updateTransferStatus(destList); + + forwardService.storeMultipleDestination(fwdNode, destList, p); + + } + catch (Exception e) { + throw new DicomServiceException(Status.ProcessingFailure, e); + } + } + + /** + * Update transfer status: if there is a transfer in progress set status to true and + * schedule a thread which will set back status to false in a certain delay. If a + * transfer is still in progress after the end of the delay, set status to true and an + * other delay is scheduled. + * @param destinations Destinations to update + */ + private void updateTransferStatus(List destinations) { + // if delay is over or first iteration + if (isDelayOver == null || isDelayOver.isDone()) { + // Set flag transfer in progress + destinations.forEach(d -> updateTransferStatus(d, true)); + // In a certain delay set back transfer in progress to false + isDelayOver = executorService.schedule(() -> destinations.forEach(d -> updateTransferStatus(d, false)), 5, + TimeUnit.SECONDS); + } + } + + /** + * Update the transfer status of a destination + * @param destination Destination to retrieve + * @param status Status to update + */ + private void updateTransferStatus(ForwardDestination destination, boolean status) { + // Retrieve the destination entity + Optional destinationEntityOptional = destinationRepo.findById(destination.getId()); + + if (destinationEntityOptional.isPresent()) { + // Update the destination transfer status if destination has been found and + // destination + // is active + DestinationEntity destinationEntity = destinationEntityOptional.get(); + if (destinationEntity.isActivate()) { + destinationEntity.setTransferInProgress(status); + destinationEntity.setLastTransfer(LocalDateTime.now(ZoneId.of("CET"))); + destinationRepo.save(destinationEntity); + } + } + } + + public Map> getDestinations() { + return destinations; + } + + public void setDestinations(Map> destinations) { + this.destinations = destinations; + } + + public int getPriority() { + return priority; + } + + public void setPriority(int priority) { + this.priority = priority; + } + + public int getStatus() { + return status; + } + + public void setStatus(int status) { + this.status = status; + } + } diff --git a/src/main/java/org/karnak/backend/service/DestinationService.java b/src/main/java/org/karnak/backend/service/DestinationService.java index df66b5e09..f0d24a9fc 100644 --- a/src/main/java/org/karnak/backend/service/DestinationService.java +++ b/src/main/java/org/karnak/backend/service/DestinationService.java @@ -23,111 +23,102 @@ @Service public class DestinationService { - // Repositories - private final DestinationRepo destinationRepo; - - // Services - private final ForwardNodeService forwardNodeService; - private final KheopsAlbumsService kheopsAlbumsService; - - // Event publisher - private final ApplicationEventPublisher applicationEventPublisher; - - /** - * Autowired constructor - * - * @param destinationRepo Destination repository - * @param forwardNodeService ForwardNode Service - * @param kheopsAlbumsService Kheops Albums Service - * @param applicationEventPublisher ApplicationEventPublisher - */ - @Autowired - public DestinationService( - final DestinationRepo destinationRepo, - final ForwardNodeService forwardNodeService, - final KheopsAlbumsService kheopsAlbumsService, - final ApplicationEventPublisher applicationEventPublisher) { - this.destinationRepo = destinationRepo; - this.forwardNodeService = forwardNodeService; - this.kheopsAlbumsService = kheopsAlbumsService; - this.applicationEventPublisher = applicationEventPublisher; - } - - /** - * Store given Destination to the backing destinationEntity service. - * - * @param forwardNodeEntity ForwardNode Entity - * @param destinationEntity the updated or new destinationEntity - */ - public DestinationEntity save( - ForwardNodeEntity forwardNodeEntity, DestinationEntity destinationEntity) { - DestinationEntity dataUpdated = - forwardNodeService.updateDestination(forwardNodeEntity, destinationEntity); - - if (destinationEntity.getId() != null) { - dataUpdated = removeValuesOnDisabledDesidentification(destinationEntity); - } - - // Refresh last transfer and email last check before saving - refreshLastTransferEmailLastCheck(dataUpdated); - - destinationRepo.saveAndFlush(dataUpdated); - kheopsAlbumsService.updateSwitchingAlbumsFromDestination(destinationEntity); - return dataUpdated; - } - - /** - * Refresh values from DB for email last check and last transfer - * - * @param destinationEntity Entity to update - */ - public void refreshLastTransferEmailLastCheck(DestinationEntity destinationEntity) { - if (destinationEntity.getId() != null) { - Optional refreshedDestinationEntityOpt = - destinationRepo.findById(destinationEntity.getId()); - if (refreshedDestinationEntityOpt.isPresent()) { - DestinationEntity destinationEntityRefreshed = refreshedDestinationEntityOpt.get(); - destinationEntity.setLastTransfer(destinationEntityRefreshed.getLastTransfer()); - destinationEntity.setEmailLastCheck(destinationEntityRefreshed.getEmailLastCheck()); - } - } - } - - private DestinationEntity removeValuesOnDisabledDesidentification( - DestinationEntity destinationEntity) { - if (!destinationEntity.isDesidentification()) { - destinationEntity.setProjectEntity(null); - } - return destinationEntity; - } - - /** - * Delete given data from the backing data service. - * - * @param destinationEntity the data to be deleted - */ - public void delete(DestinationEntity destinationEntity) { - ForwardNodeEntity forwardNodeEntityOfDest = destinationEntity.getForwardNodeEntity(); - if (forwardNodeEntityOfDest != null) { - forwardNodeService.deleteDestination(forwardNodeEntityOfDest, destinationEntity); - } - } - - public ApplicationEventPublisher getApplicationEventPublisher() { - return applicationEventPublisher; - } - - /** - * Retrieve destinations of a forward node - * - * @param forwardNodeEntity forward node - * @return destinations found - */ - public Collection retrieveDestinations(ForwardNodeEntity forwardNodeEntity) { - return forwardNodeService.getAllDestinations(forwardNodeEntity); - } - - public List retrieveDestinationsFromIds(List ids) { - return destinationRepo.findAllById(ids); - } + // Repositories + private final DestinationRepo destinationRepo; + + // Services + private final ForwardNodeService forwardNodeService; + + private final KheopsAlbumsService kheopsAlbumsService; + + // Event publisher + private final ApplicationEventPublisher applicationEventPublisher; + + /** + * Autowired constructor + * @param destinationRepo Destination repository + * @param forwardNodeService ForwardNode Service + * @param kheopsAlbumsService Kheops Albums Service + * @param applicationEventPublisher ApplicationEventPublisher + */ + @Autowired + public DestinationService(final DestinationRepo destinationRepo, final ForwardNodeService forwardNodeService, + final KheopsAlbumsService kheopsAlbumsService, final ApplicationEventPublisher applicationEventPublisher) { + this.destinationRepo = destinationRepo; + this.forwardNodeService = forwardNodeService; + this.kheopsAlbumsService = kheopsAlbumsService; + this.applicationEventPublisher = applicationEventPublisher; + } + + /** + * Store given Destination to the backing destinationEntity service. + * @param forwardNodeEntity ForwardNode Entity + * @param destinationEntity the updated or new destinationEntity + */ + public DestinationEntity save(ForwardNodeEntity forwardNodeEntity, DestinationEntity destinationEntity) { + DestinationEntity dataUpdated = forwardNodeService.updateDestination(forwardNodeEntity, destinationEntity); + + if (destinationEntity.getId() != null) { + dataUpdated = removeValuesOnDisabledDesidentification(destinationEntity); + } + + // Refresh last transfer and email last check before saving + refreshLastTransferEmailLastCheck(dataUpdated); + + destinationRepo.saveAndFlush(dataUpdated); + kheopsAlbumsService.updateSwitchingAlbumsFromDestination(destinationEntity); + return dataUpdated; + } + + /** + * Refresh values from DB for email last check and last transfer + * @param destinationEntity Entity to update + */ + public void refreshLastTransferEmailLastCheck(DestinationEntity destinationEntity) { + if (destinationEntity.getId() != null) { + Optional refreshedDestinationEntityOpt = destinationRepo + .findById(destinationEntity.getId()); + if (refreshedDestinationEntityOpt.isPresent()) { + DestinationEntity destinationEntityRefreshed = refreshedDestinationEntityOpt.get(); + destinationEntity.setLastTransfer(destinationEntityRefreshed.getLastTransfer()); + destinationEntity.setEmailLastCheck(destinationEntityRefreshed.getEmailLastCheck()); + } + } + } + + private DestinationEntity removeValuesOnDisabledDesidentification(DestinationEntity destinationEntity) { + if (!destinationEntity.isDesidentification()) { + destinationEntity.setProjectEntity(null); + } + return destinationEntity; + } + + /** + * Delete given data from the backing data service. + * @param destinationEntity the data to be deleted + */ + public void delete(DestinationEntity destinationEntity) { + ForwardNodeEntity forwardNodeEntityOfDest = destinationEntity.getForwardNodeEntity(); + if (forwardNodeEntityOfDest != null) { + forwardNodeService.deleteDestination(forwardNodeEntityOfDest, destinationEntity); + } + } + + public ApplicationEventPublisher getApplicationEventPublisher() { + return applicationEventPublisher; + } + + /** + * Retrieve destinations of a forward node + * @param forwardNodeEntity forward node + * @return destinations found + */ + public Collection retrieveDestinations(ForwardNodeEntity forwardNodeEntity) { + return forwardNodeService.getAllDestinations(forwardNodeEntity); + } + + public List retrieveDestinationsFromIds(List ids) { + return destinationRepo.findAllById(ids); + } + } diff --git a/src/main/java/org/karnak/backend/service/DicomGatewayService.java b/src/main/java/org/karnak/backend/service/DicomGatewayService.java index 12131aa6f..63c574a0a 100644 --- a/src/main/java/org/karnak/backend/service/DicomGatewayService.java +++ b/src/main/java/org/karnak/backend/service/DicomGatewayService.java @@ -28,105 +28,98 @@ @Service public class DicomGatewayService { - private final StoreScpForwardService storeScpForwardService; - private DeviceListenerService deviceService; - - @Autowired - public DicomGatewayService(final StoreScpForwardService storeScpForwardService) { - this.storeScpForwardService = storeScpForwardService; - } - - /** - * Init a DICOM Gateway with one final destination - * - * @param forwardParams the optional advanced parameters (proxy, authentication, connection and - * TLS) for the final destination - * @param fwdNode the calling DICOM node configuration - * @param destinationNode the final DICOM node configuration - * @throws IOException - */ - public void init( - AdvancedParams forwardParams, ForwardDicomNode fwdNode, DicomNode destinationNode) - throws IOException { - init(forwardParams, fwdNode, destinationNode, null); - } - - /** - * Init a DICOM Gateway with one final destination - * - * @param forwardParams the optional advanced parameters (proxy, authentication, connection and - * TLS) for the final destination - * @param fwdNode the calling DICOM node configuration - * @param destinationNode the final DICOM node configuration - * @param editors the list of editor for modifying attributes on the fly (can be Null) - * @throws IOException - */ - public void init( - AdvancedParams forwardParams, - ForwardDicomNode fwdNode, - DicomNode destinationNode, - List editors) - throws IOException { - storeScpForwardService.init(forwardParams, fwdNode, destinationNode, editors); - this.deviceService = new DeviceListenerService(storeScpForwardService.getDevice()); - } - - public void init(Map> destinations) - throws IOException { - storeScpForwardService.init(destinations); - this.deviceService = new DeviceListenerService(storeScpForwardService.getDevice()); - } - - public boolean isRunning() { - return storeScpForwardService.getConnection().isListening(); - } - - public StoreScpForwardService getStoreScpForward() { - return storeScpForwardService; - } - - public void start(DicomNode scpNode) throws Exception { - start(scpNode, new GatewayParams(false)); - } - - public synchronized void start(DicomNode scpNode, GatewayParams params) throws Exception { - if (isRunning()) { - throw new IOException("Cannot start a DICOM Gateway because it is already running."); - } - storeScpForwardService.setStatus(0); - storeScpForwardService.getCstoreSCP().setStatus(0); - - AdvancedParams options = Objects.requireNonNull(params).getParams(); - Connection conn = storeScpForwardService.getConnection(); - if (params.isBindCallingAet()) { - options.configureBind(storeScpForwardService.getApplicationEntity(), conn, scpNode); - } else { - options.configureBind(conn, scpNode); - } - // configure - options.configure(conn); - options.configureTLS(conn, null); - - // Limit the calling AETs - storeScpForwardService - .getApplicationEntity() - .setAcceptedCallingAETitles(params.getAcceptedCallingAETitles()); - - URL transferCapabilityFile = params.getTransferCapabilityFile(); - if (transferCapabilityFile != null) { - storeScpForwardService.loadDefaultTransferCapability(transferCapabilityFile); - } else { - storeScpForwardService - .getApplicationEntity() - .addTransferCapability( - new TransferCapability(null, "*", TransferCapability.Role.SCP, "*")); - } - - deviceService.start(); - } - - public synchronized void stop() { - deviceService.stop(); - storeScpForwardService.stop(); - } + + private final StoreScpForwardService storeScpForwardService; + + private DeviceListenerService deviceService; + + @Autowired + public DicomGatewayService(final StoreScpForwardService storeScpForwardService) { + this.storeScpForwardService = storeScpForwardService; + } + + /** + * Init a DICOM Gateway with one final destination + * @param forwardParams the optional advanced parameters (proxy, authentication, + * connection and TLS) for the final destination + * @param fwdNode the calling DICOM node configuration + * @param destinationNode the final DICOM node configuration + * @throws IOException + */ + public void init(AdvancedParams forwardParams, ForwardDicomNode fwdNode, DicomNode destinationNode) + throws IOException { + init(forwardParams, fwdNode, destinationNode, null); + } + + /** + * Init a DICOM Gateway with one final destination + * @param forwardParams the optional advanced parameters (proxy, authentication, + * connection and TLS) for the final destination + * @param fwdNode the calling DICOM node configuration + * @param destinationNode the final DICOM node configuration + * @param editors the list of editor for modifying attributes on the fly (can be Null) + * @throws IOException + */ + public void init(AdvancedParams forwardParams, ForwardDicomNode fwdNode, DicomNode destinationNode, + List editors) throws IOException { + storeScpForwardService.init(forwardParams, fwdNode, destinationNode, editors); + this.deviceService = new DeviceListenerService(storeScpForwardService.getDevice()); + } + + public void init(Map> destinations) throws IOException { + storeScpForwardService.init(destinations); + this.deviceService = new DeviceListenerService(storeScpForwardService.getDevice()); + } + + public boolean isRunning() { + return storeScpForwardService.getConnection().isListening(); + } + + public StoreScpForwardService getStoreScpForward() { + return storeScpForwardService; + } + + public void start(DicomNode scpNode) throws Exception { + start(scpNode, new GatewayParams(false)); + } + + public synchronized void start(DicomNode scpNode, GatewayParams params) throws Exception { + if (isRunning()) { + throw new IOException("Cannot start a DICOM Gateway because it is already running."); + } + storeScpForwardService.setStatus(0); + storeScpForwardService.getCstoreSCP().setStatus(0); + + AdvancedParams options = Objects.requireNonNull(params).getParams(); + Connection conn = storeScpForwardService.getConnection(); + if (params.isBindCallingAet()) { + options.configureBind(storeScpForwardService.getApplicationEntity(), conn, scpNode); + } + else { + options.configureBind(conn, scpNode); + } + // configure + options.configure(conn); + options.configureTLS(conn, null); + + // Limit the calling AETs + storeScpForwardService.getApplicationEntity().setAcceptedCallingAETitles(params.getAcceptedCallingAETitles()); + + URL transferCapabilityFile = params.getTransferCapabilityFile(); + if (transferCapabilityFile != null) { + storeScpForwardService.loadDefaultTransferCapability(transferCapabilityFile); + } + else { + storeScpForwardService.getApplicationEntity() + .addTransferCapability(new TransferCapability(null, "*", TransferCapability.Role.SCP, "*")); + } + + deviceService.start(); + } + + public synchronized void stop() { + deviceService.stop(); + storeScpForwardService.stop(); + } + } diff --git a/src/main/java/org/karnak/backend/service/EchoService.java b/src/main/java/org/karnak/backend/service/EchoService.java index f63c2dd59..5a13ce5aa 100644 --- a/src/main/java/org/karnak/backend/service/EchoService.java +++ b/src/main/java/org/karnak/backend/service/EchoService.java @@ -31,82 +31,71 @@ @Service public class EchoService { - private static final Logger LOGGER = LoggerFactory.getLogger(EchoService.class); + private static final Logger LOGGER = LoggerFactory.getLogger(EchoService.class); - // Service - private final GatewaySetUpService gatewaySetUpService; + // Service + private final GatewaySetUpService gatewaySetUpService; - @Autowired - public EchoService(final GatewaySetUpService gatewaySetUpService) { - this.gatewaySetUpService = gatewaySetUpService; - } + @Autowired + public EchoService(final GatewaySetUpService gatewaySetUpService) { + this.gatewaySetUpService = gatewaySetUpService; + } - /** - * Retrieve the configured destinations from the setup - * - * @return List of configured destinations - * @param sourceAet Source AeTitle - */ - public List retrieveStatusConfiguredDestinations(String sourceAet) { - List destinationEchos = new ArrayList<>(); + /** + * Retrieve the configured destinations from the setup + * @return List of configured destinations + * @param sourceAet Source AeTitle + */ + public List retrieveStatusConfiguredDestinations(String sourceAet) { + List destinationEchos = new ArrayList<>(); - // Fill the list of destinations status - gatewaySetUpService - .getDestinationNode(sourceAet) - .ifPresent( - sourceNode -> - fillDestinationsStatus( - destinationEchos, sourceNode, gatewaySetUpService.getDestinations(sourceNode))); + // Fill the list of destinations status + gatewaySetUpService.getDestinationNode(sourceAet) + .ifPresent(sourceNode -> fillDestinationsStatus(destinationEchos, sourceNode, + gatewaySetUpService.getDestinations(sourceNode))); - return destinationEchos; - } + return destinationEchos; + } - /** - * Fill the list of destinations status - * - * @param destinationEchos List to fill - * @param sourceNode Source Node - * @param destinations Destinations found - */ - private void fillDestinationsStatus( - List destinationEchos, - ForwardDicomNode sourceNode, - List destinations) { - destinations.forEach( - destination -> { - // Case DICOM - if (destination instanceof DicomForwardDestination) { - DicomNode calledNode = - ((DicomForwardDestination) destination).getStreamSCU().getCalledNode(); - // Retrieve the status of the dicom node - DicomState dicomState = - Echo.process(buildEchoProcessParams(3000, 5000), sourceNode, calledNode); - // Add the destination and its status - destinationEchos.add( - new DestinationEcho(calledNode.getAet(), null, dicomState.getStatus())); - } - // Case Stow - else if (destination instanceof WebForwardDestination) { - WebForwardDestination d = (WebForwardDestination) destination; - // Add the destination and its status - destinationEchos.add(new DestinationEcho(null, d.getRequestURL(), 0)); - } - }); - } + /** + * Fill the list of destinations status + * @param destinationEchos List to fill + * @param sourceNode Source Node + * @param destinations Destinations found + */ + private void fillDestinationsStatus(List destinationEchos, ForwardDicomNode sourceNode, + List destinations) { + destinations.forEach(destination -> { + // Case DICOM + if (destination instanceof DicomForwardDestination) { + DicomNode calledNode = ((DicomForwardDestination) destination).getStreamSCU().getCalledNode(); + // Retrieve the status of the dicom node + DicomState dicomState = Echo.process(buildEchoProcessParams(3000, 5000), sourceNode, calledNode); + // Add the destination and its status + destinationEchos.add(new DestinationEcho(calledNode.getAet(), null, dicomState.getStatus())); + } + // Case Stow + else if (destination instanceof WebForwardDestination) { + WebForwardDestination d = (WebForwardDestination) destination; + // Add the destination and its status + destinationEchos.add(new DestinationEcho(null, d.getRequestURL(), 0)); + } + }); + } + + /** + * Build params for echo process call + * @param connectTimeout Connect Timeout + * @param acceptTimeout Accept Timeout + * @return parameters built + */ + private AdvancedParams buildEchoProcessParams(int connectTimeout, int acceptTimeout) { + AdvancedParams params = new AdvancedParams(); + ConnectOptions connectOptions = new ConnectOptions(); + connectOptions.setConnectTimeout(connectTimeout); + connectOptions.setAcceptTimeout(acceptTimeout); + params.setConnectOptions(connectOptions); + return params; + } - /** - * Build params for echo process call - * - * @param connectTimeout Connect Timeout - * @param acceptTimeout Accept Timeout - * @return parameters built - */ - private AdvancedParams buildEchoProcessParams(int connectTimeout, int acceptTimeout) { - AdvancedParams params = new AdvancedParams(); - ConnectOptions connectOptions = new ConnectOptions(); - connectOptions.setConnectTimeout(connectTimeout); - connectOptions.setAcceptTimeout(acceptTimeout); - params.setConnectOptions(connectOptions); - return params; - } } diff --git a/src/main/java/org/karnak/backend/service/FileService.java b/src/main/java/org/karnak/backend/service/FileService.java index 2356d7cc0..d149f1b30 100644 --- a/src/main/java/org/karnak/backend/service/FileService.java +++ b/src/main/java/org/karnak/backend/service/FileService.java @@ -14,46 +14,47 @@ // @Service // public class FileService { // -// private static final Logger LOGGER = LoggerFactory.getLogger(FileService.class); +// private static final Logger LOGGER = LoggerFactory.getLogger(FileService.class); // -// // Service -// private final GatewaySetUpService gatewaySetUpService; +// // Service +// private final GatewaySetUpService gatewaySetUpService; // -// @Autowired -// public FileService(final GatewaySetUpService gatewaySetUpService) { -// this.gatewaySetUpService = gatewaySetUpService; -// } +// @Autowired +// public FileService(final GatewaySetUpService gatewaySetUpService) { +// this.gatewaySetUpService = gatewaySetUpService; +// } // -// /** -// * Retrieve the file to download -// * -// * @param aet AeTitle -// * @param fileName File name -// * @return File to download -// * @throws IOException IO Exception -// * @throws IllegalStateException Illegal State Exception -// */ -// public byte[] retrieveFileToDownload(String aet, String fileName) -// throws IOException, IllegalStateException { +// /** +// * Retrieve the file to download +// * +// * @param aet AeTitle +// * @param fileName File name +// * @return File to download +// * @throws IOException IO Exception +// * @throws IllegalStateException Illegal State Exception +// */ +// public byte[] retrieveFileToDownload(String aet, String fileName) +// throws IOException, IllegalStateException { // -// // Stored Path to get file from -// final Path archiveDir = gatewaySetUpService.getStorePath(); +// // Stored Path to get file from +// final Path archiveDir = gatewaySetUpService.getStorePath(); // -// // If path is not valid throw an exception -// if (archiveDir == null || !Files.isDirectory(archiveDir) || !Files.isReadable(archiveDir)) { -// throw new IllegalStateException("Cannot access to the archive directory"); -// } else { -// if (aet != null && fileName != null) { -// Path path = Path.of(archiveDir.toString(), aet, fileName); -// if (path == null || !Files.isReadable(path)) { -// LOGGER.warn("Cannot get this file for downloading: {}", path); -// } else { -// // Return the file -// DataInputStream in = new DataInputStream(Files.newInputStream(path)); -// return IOUtils.toByteArray(in); -// } -// } -// } -// return null; -// } +// // If path is not valid throw an exception +// if (archiveDir == null || !Files.isDirectory(archiveDir) || +// !Files.isReadable(archiveDir)) { +// throw new IllegalStateException("Cannot access to the archive directory"); +// } else { +// if (aet != null && fileName != null) { +// Path path = Path.of(archiveDir.toString(), aet, fileName); +// if (path == null || !Files.isReadable(path)) { +// LOGGER.warn("Cannot get this file for downloading: {}", path); +// } else { +// // Return the file +// DataInputStream in = new DataInputStream(Files.newInputStream(path)); +// return IOUtils.toByteArray(in); +// } +// } +// } +// return null; +// } // } diff --git a/src/main/java/org/karnak/backend/service/ForwardNodeAPIService.java b/src/main/java/org/karnak/backend/service/ForwardNodeAPIService.java index 86668f97a..5b118347f 100644 --- a/src/main/java/org/karnak/backend/service/ForwardNodeAPIService.java +++ b/src/main/java/org/karnak/backend/service/ForwardNodeAPIService.java @@ -22,60 +22,56 @@ @Service public class ForwardNodeAPIService implements Serializable { - // Services - private final ForwardNodeService forwardNodeService; - private final DestinationService destinationService; + // Services + private final ForwardNodeService forwardNodeService; - // Event publisher - private final ApplicationEventPublisher applicationEventPublisher; + private final DestinationService destinationService; - @Autowired - public ForwardNodeAPIService( - final ForwardNodeService forwardNodeService, - final DestinationService destinationService, - final ApplicationEventPublisher applicationEventPublisher) { - this.forwardNodeService = forwardNodeService; - this.destinationService = destinationService; - this.applicationEventPublisher = applicationEventPublisher; - } + // Event publisher + private final ApplicationEventPublisher applicationEventPublisher; - public ForwardNodeService getDataProvider() { - return forwardNodeService; - } + @Autowired + public ForwardNodeAPIService(final ForwardNodeService forwardNodeService, + final DestinationService destinationService, final ApplicationEventPublisher applicationEventPublisher) { + this.forwardNodeService = forwardNodeService; + this.destinationService = destinationService; + this.applicationEventPublisher = applicationEventPublisher; + } - public void addForwardNode(ForwardNodeEntity forwardNodeEntity) { - NodeEventType eventType = - forwardNodeEntity.getId() == null ? NodeEventType.ADD : NodeEventType.UPDATE; - if (eventType == NodeEventType.ADD) { - Optional val = - forwardNodeService.getAllForwardNodes().stream() - .filter(f -> f.getFwdAeTitle().equals(forwardNodeEntity.getFwdAeTitle())) - .findFirst(); - if (val.isPresent()) { - // showError("Cannot add this new node because the AE-Title already exists!"); - return; - } - } - forwardNodeService.save(forwardNodeEntity); - applicationEventPublisher.publishEvent(new NodeEvent(forwardNodeEntity, eventType)); - } + public ForwardNodeService getDataProvider() { + return forwardNodeService; + } - public void updateForwardNode(ForwardNodeEntity forwardNodeEntity) { - // Refresh last transfer and email last check - forwardNodeEntity - .getDestinationEntities() - .forEach(destinationService::refreshLastTransferEmailLastCheck); - // Save forward entity - forwardNodeService.save(forwardNodeEntity); - applicationEventPublisher.publishEvent(new NodeEvent(forwardNodeEntity, NodeEventType.UPDATE)); - } + public void addForwardNode(ForwardNodeEntity forwardNodeEntity) { + NodeEventType eventType = forwardNodeEntity.getId() == null ? NodeEventType.ADD : NodeEventType.UPDATE; + if (eventType == NodeEventType.ADD) { + Optional val = forwardNodeService.getAllForwardNodes().stream() + .filter(f -> f.getFwdAeTitle().equals(forwardNodeEntity.getFwdAeTitle())).findFirst(); + if (val.isPresent()) { + // showError("Cannot add this new node because the AE-Title already + // exists!"); + return; + } + } + forwardNodeService.save(forwardNodeEntity); + applicationEventPublisher.publishEvent(new NodeEvent(forwardNodeEntity, eventType)); + } - public void deleteForwardNode(ForwardNodeEntity forwardNodeEntity) { - forwardNodeService.delete(forwardNodeEntity); - applicationEventPublisher.publishEvent(new NodeEvent(forwardNodeEntity, NodeEventType.REMOVE)); - } + public void updateForwardNode(ForwardNodeEntity forwardNodeEntity) { + // Refresh last transfer and email last check + forwardNodeEntity.getDestinationEntities().forEach(destinationService::refreshLastTransferEmailLastCheck); + // Save forward entity + forwardNodeService.save(forwardNodeEntity); + applicationEventPublisher.publishEvent(new NodeEvent(forwardNodeEntity, NodeEventType.UPDATE)); + } + + public void deleteForwardNode(ForwardNodeEntity forwardNodeEntity) { + forwardNodeService.delete(forwardNodeEntity); + applicationEventPublisher.publishEvent(new NodeEvent(forwardNodeEntity, NodeEventType.REMOVE)); + } + + public ForwardNodeEntity getForwardNodeById(Long dataId) { + return forwardNodeService.get(dataId); + } - public ForwardNodeEntity getForwardNodeById(Long dataId) { - return forwardNodeService.get(dataId); - } } diff --git a/src/main/java/org/karnak/backend/service/ForwardNodeService.java b/src/main/java/org/karnak/backend/service/ForwardNodeService.java index 89d06e6fe..ed8bac8bf 100644 --- a/src/main/java/org/karnak/backend/service/ForwardNodeService.java +++ b/src/main/java/org/karnak/backend/service/ForwardNodeService.java @@ -23,121 +23,116 @@ @Service public class ForwardNodeService { - // Repositories - private final ForwardNodeRepo forwardNodeRepo; - - @Autowired - public ForwardNodeService(final ForwardNodeRepo forwardNodeRepo) { - this.forwardNodeRepo = forwardNodeRepo; - } - - /** - * Retrieves the ForwardNode according to its ID. - * - * @param dataId the data ID. - * @return the ForwardNodeEntity according to its ID; null if not found. - */ - public ForwardNodeEntity get(Long dataId) { - return forwardNodeRepo.findById(dataId).orElse(null); - } - - /** - * Store given ForwardNode. - * - * @param forwardNodeEntity the updated or new forwardNodeEntity - */ - public void save(ForwardNodeEntity forwardNodeEntity) { - // Save forward node - forwardNodeRepo.saveAndFlush(forwardNodeEntity); - } - - /** - * Delete given data from the backing data service. - * - * @param data the data to be deleted - */ - public void delete(ForwardNodeEntity data) { - forwardNodeRepo.deleteById(data.getId()); - forwardNodeRepo.flush(); - } - - public List getAllForwardNodes() { - return forwardNodeRepo.findAll(); - } - - public Collection getAllDestinations(ForwardNodeEntity forwardNodeEntity) { - if (forwardNodeEntity != null) { - return forwardNodeEntity.getDestinationEntities(); - } - return new HashSet<>(); - } - - public DestinationEntity getDestinationById(ForwardNodeEntity forwardNodeEntity, Long dataId) { - Collection destinationEntities = getAllDestinations(forwardNodeEntity); - for (DestinationEntity destinationEntity : destinationEntities) { - if (Objects.equals(destinationEntity.getId(), dataId)) { - return destinationEntity; - } - } - return null; - } - - public DestinationEntity updateDestination( - ForwardNodeEntity forwardNodeEntity, DestinationEntity data) { - if (forwardNodeEntity == null || data == null) { - return null; - } - Collection destinationEntities = getAllDestinations(forwardNodeEntity); - if (!destinationEntities.contains(data)) { - forwardNodeEntity.addDestination(data); - } - return data; - } - - public void deleteDestination(ForwardNodeEntity forwardNodeEntity, DestinationEntity data) { - if (forwardNodeEntity == null || data == null) { - return; - } - forwardNodeEntity.removeDestination(data); - forwardNodeRepo.saveAndFlush(forwardNodeEntity); - } - - public Collection getAllSourceNodes(ForwardNodeEntity forwardNodeEntity) { - if (forwardNodeEntity != null) { - return forwardNodeEntity.getSourceNodes(); - } - return new HashSet<>(); - } - - public DicomSourceNodeEntity getSourceNodeById(ForwardNodeEntity forwardNodeEntity, Long dataId) { - Collection sourceNodes = getAllSourceNodes(forwardNodeEntity); - for (DicomSourceNodeEntity sourceNode : sourceNodes) { - if (Objects.equals(sourceNode.getId(), dataId)) { - return sourceNode; - } - } - return null; - } - - public DicomSourceNodeEntity updateSourceNode( - ForwardNodeEntity forwardNodeEntity, DicomSourceNodeEntity data) { - if (forwardNodeEntity == null || data == null) { - return null; - } - Collection sourceNodes = getAllSourceNodes(forwardNodeEntity); - if (!sourceNodes.contains(data)) { - forwardNodeEntity.addSourceNode(data); - } - forwardNodeRepo.saveAndFlush(forwardNodeEntity); - return data; - } - - public void deleteSourceNode( - ForwardNodeEntity forwardNodeEntity, DicomSourceNodeEntity dicomSourceNodeEntity) { - if (forwardNodeEntity == null || dicomSourceNodeEntity == null) { - return; - } - forwardNodeEntity.removeSourceNode(dicomSourceNodeEntity); - forwardNodeRepo.saveAndFlush(forwardNodeEntity); - } + // Repositories + private final ForwardNodeRepo forwardNodeRepo; + + @Autowired + public ForwardNodeService(final ForwardNodeRepo forwardNodeRepo) { + this.forwardNodeRepo = forwardNodeRepo; + } + + /** + * Retrieves the ForwardNode according to its ID. + * @param dataId the data ID. + * @return the ForwardNodeEntity according to its ID; null if not found. + */ + public ForwardNodeEntity get(Long dataId) { + return forwardNodeRepo.findById(dataId).orElse(null); + } + + /** + * Store given ForwardNode. + * @param forwardNodeEntity the updated or new forwardNodeEntity + */ + public void save(ForwardNodeEntity forwardNodeEntity) { + // Save forward node + forwardNodeRepo.saveAndFlush(forwardNodeEntity); + } + + /** + * Delete given data from the backing data service. + * @param data the data to be deleted + */ + public void delete(ForwardNodeEntity data) { + forwardNodeRepo.deleteById(data.getId()); + forwardNodeRepo.flush(); + } + + public List getAllForwardNodes() { + return forwardNodeRepo.findAll(); + } + + public Collection getAllDestinations(ForwardNodeEntity forwardNodeEntity) { + if (forwardNodeEntity != null) { + return forwardNodeEntity.getDestinationEntities(); + } + return new HashSet<>(); + } + + public DestinationEntity getDestinationById(ForwardNodeEntity forwardNodeEntity, Long dataId) { + Collection destinationEntities = getAllDestinations(forwardNodeEntity); + for (DestinationEntity destinationEntity : destinationEntities) { + if (Objects.equals(destinationEntity.getId(), dataId)) { + return destinationEntity; + } + } + return null; + } + + public DestinationEntity updateDestination(ForwardNodeEntity forwardNodeEntity, DestinationEntity data) { + if (forwardNodeEntity == null || data == null) { + return null; + } + Collection destinationEntities = getAllDestinations(forwardNodeEntity); + if (!destinationEntities.contains(data)) { + forwardNodeEntity.addDestination(data); + } + return data; + } + + public void deleteDestination(ForwardNodeEntity forwardNodeEntity, DestinationEntity data) { + if (forwardNodeEntity == null || data == null) { + return; + } + forwardNodeEntity.removeDestination(data); + forwardNodeRepo.saveAndFlush(forwardNodeEntity); + } + + public Collection getAllSourceNodes(ForwardNodeEntity forwardNodeEntity) { + if (forwardNodeEntity != null) { + return forwardNodeEntity.getSourceNodes(); + } + return new HashSet<>(); + } + + public DicomSourceNodeEntity getSourceNodeById(ForwardNodeEntity forwardNodeEntity, Long dataId) { + Collection sourceNodes = getAllSourceNodes(forwardNodeEntity); + for (DicomSourceNodeEntity sourceNode : sourceNodes) { + if (Objects.equals(sourceNode.getId(), dataId)) { + return sourceNode; + } + } + return null; + } + + public DicomSourceNodeEntity updateSourceNode(ForwardNodeEntity forwardNodeEntity, DicomSourceNodeEntity data) { + if (forwardNodeEntity == null || data == null) { + return null; + } + Collection sourceNodes = getAllSourceNodes(forwardNodeEntity); + if (!sourceNodes.contains(data)) { + forwardNodeEntity.addSourceNode(data); + } + forwardNodeRepo.saveAndFlush(forwardNodeEntity); + return data; + } + + public void deleteSourceNode(ForwardNodeEntity forwardNodeEntity, DicomSourceNodeEntity dicomSourceNodeEntity) { + if (forwardNodeEntity == null || dicomSourceNodeEntity == null) { + return; + } + forwardNodeEntity.removeSourceNode(dicomSourceNodeEntity); + forwardNodeRepo.saveAndFlush(forwardNodeEntity); + } + } diff --git a/src/main/java/org/karnak/backend/service/ForwardService.java b/src/main/java/org/karnak/backend/service/ForwardService.java index 1a9289946..da78ca91a 100644 --- a/src/main/java/org/karnak/backend/service/ForwardService.java +++ b/src/main/java/org/karnak/backend/service/ForwardService.java @@ -61,614 +61,535 @@ @Service public class ForwardService { - private static final String ERROR_WHEN_FORWARDING = - "Error when forwarding to the final destination"; - - private static final Logger LOGGER = LoggerFactory.getLogger(ForwardService.class); - - private final ApplicationEventPublisher applicationEventPublisher; - - @Autowired - public ForwardService(final ApplicationEventPublisher applicationEventPublisher) { - this.applicationEventPublisher = applicationEventPublisher; - } - - public void storeMultipleDestination( - ForwardDicomNode fwdNode, List destList, Params p) throws IOException { - if (destList == null || destList.isEmpty()) { - throw new IllegalStateException( - "Cannot find the DICOM destination from " + fwdNode.toString()); - } - // Exclude DICOMDIR - if ("1.2.840.10008.1.3.10".equals(p.getCuid())) { - LOGGER.warn("Cannot send DICOMDIR {}", p.getIuid()); - return; - } - - if (destList.size() == 1) { - storeOneDestination(fwdNode, destList.get(0), p); - } else { - List destConList = new ArrayList<>(); - for (ForwardDestination fwDest : destList) { - try { - if (fwDest instanceof DicomForwardDestination) { - prepareTransfer((DicomForwardDestination) fwDest, p); - } - destConList.add(fwDest); - } catch (Exception e) { - LOGGER.error("Cannot connect to the final destination", e); - } - } - - if (destConList.isEmpty()) { - return; - } else if (destConList.size() == 1) { - storeOneDestination(fwdNode, destConList.get(0), p); - } else { - List files = null; - try { - Attributes attributes = new Attributes(); - ForwardDestination fistDest = destConList.get(0); - if (fistDest instanceof DicomForwardDestination) { - files = transfer(fwdNode, (DicomForwardDestination) fistDest, attributes, p); - } else if (fistDest instanceof WebForwardDestination) { - files = transfer(fwdNode, (WebForwardDestination) fistDest, attributes, p); - } - if (!attributes.isEmpty()) { - for (int i = 1; i < destConList.size(); i++) { - ForwardDestination dest = destConList.get(i); - if (dest instanceof DicomForwardDestination) { - transferOther(fwdNode, (DicomForwardDestination) dest, attributes, p); - } else if (dest instanceof WebForwardDestination) { - transferOther(fwdNode, (WebForwardDestination) dest, attributes, p); - } - } - } - } finally { - if (files != null) { - // Force to clean if tmp bulk files - for (File file : files) { - FileUtil.delete(file); - } - } - } - } - } - } - - public void storeOneDestination( - ForwardDicomNode fwdNode, ForwardDestination destination, Params p) throws IOException { - if (destination instanceof DicomForwardDestination) { - DicomForwardDestination dest = (DicomForwardDestination) destination; - prepareTransfer(dest, p); - transfer(fwdNode, dest, null, p); - } else if (destination instanceof WebForwardDestination) { - transfer(fwdNode, (WebForwardDestination) destination, null, p); - } - } - - public static synchronized StoreFromStreamSCU prepareTransfer( - DicomForwardDestination destination, Params p) throws IOException { - String cuid = p.getCuid(); - String tsuid = p.getTsuid(); - String dstTsuid = destination.getOutputTransferSyntax(tsuid); - StoreFromStreamSCU streamSCU = destination.getStreamSCU(); - - if (streamSCU.hasAssociation()) { - // Handle dynamically new SOPClassUID - Set tss = streamSCU.getTransferSyntaxesFor(cuid); - if (!tss.contains(dstTsuid)) { - streamSCU.close(true); - } - - // Add Presentation Context for the association - streamSCU.addData(cuid, dstTsuid); - if (DicomOutputData.isAdaptableSyntax(dstTsuid)) { - streamSCU.addData(cuid, UID.JPEGLosslessSV1); - } - - if (!streamSCU.isReadyForDataTransfer()) { - // If connection has been closed just reopen - streamSCU.open(); - } - } else { - destination.getStreamSCUService().start(); - // Add Presentation Context for the association - streamSCU.addData(cuid, dstTsuid); - if (!dstTsuid.equals(UID.ExplicitVRLittleEndian)) { - streamSCU.addData(cuid, UID.ExplicitVRLittleEndian); - } - if (DicomOutputData.isAdaptableSyntax(dstTsuid)) { - streamSCU.addData(cuid, UID.JPEGLosslessSV1); - } - streamSCU.open(); - } - return streamSCU; - } - - public List transfer( - ForwardDicomNode sourceNode, DicomForwardDestination destination, Attributes copy, Params p) - throws IOException { - StoreFromStreamSCU streamSCU = destination.getStreamSCU(); - DicomInputStream in = null; - List files; - Attributes attributesOriginal = new Attributes(); - Attributes attributesToSend = new Attributes(); - try { - if (!streamSCU.isReadyForDataTransfer()) { - throw new IllegalStateException("Association not ready for transfer."); - } - DataWriter dataWriter; - String cuid = p.getCuid(); - String iuid = p.getIuid(); - String tsuid = p.getTsuid(); - var syntax = - new AdaptTransferSyntax( - tsuid, - streamSCU.selectTransferSyntax(cuid, destination.getOutputTransferSyntax(tsuid))); - List editors = destination.getDicomEditors(); - - if (copy == null && editors.isEmpty() && syntax.getRequested().equals(tsuid)) { - dataWriter = new InputStreamDataWriter(p.getData()); - attributesToSend = new DicomInputStream(p.getData()).readDataset(); - attributesOriginal.addAll(attributesToSend); - } else { - AttributeEditorContext context = - new AttributeEditorContext(tsuid, sourceNode, streamSCU.getRemoteDicomNode()); - in = new DicomInputStream(p.getData(), tsuid); - in.setIncludeBulkData(IncludeBulkData.URI); - Attributes attributes = in.readDataset(); - attributesOriginal.addAll(attributes); - attributesToSend = attributes; - if (copy != null) { - copy.addAll(attributes); - } - - if (!editors.isEmpty()) { - editors.forEach(e -> e.apply(attributes, context)); - iuid = attributes.getString(Tag.SOPInstanceUID); - cuid = attributes.getString(Tag.SOPClassUID); - } - - if (context.getAbort() == Abort.FILE_EXCEPTION) { - if (p.getData() instanceof PDVInputStream) { - ((PDVInputStream) p.getData()).skipAll(); - } - throw new AbortException(context.getAbort(), context.getAbortMessage()); - } else if (context.getAbort() == Abort.CONNECTION_EXCEPTION) { - if (p.getAs() != null) { - p.getAs().abort(); - } - throw new AbortException( - context.getAbort(), "DICOM association abort: " + context.getAbortMessage()); - } - - BytesWithImageDescriptor desc = ImageAdapter.imageTranscode(attributes, syntax, context); - Editable editable = transformImage(attributes, context); - dataWriter = ImageAdapter.buildDataWriter(attributes, syntax, editable, desc); - } - - streamSCU.cstore(cuid, iuid, p.getPriority(), dataWriter, syntax.getSuitable()); - progressNotify( - destination, p.getIuid(), p.getCuid(), false, streamSCU.getNumberOfSuboperations()); - monitor( - sourceNode.getId(), - destination.getId(), - attributesOriginal, - attributesToSend, - true, - null); - } catch (AbortException e) { - progressNotify( - destination, p.getIuid(), p.getCuid(), true, streamSCU.getNumberOfSuboperations()); - monitor( - sourceNode.getId(), - destination.getId(), - attributesOriginal, - attributesToSend, - false, - e.getMessage()); - if (e.getAbort() == Abort.CONNECTION_EXCEPTION) { - throw e; - } - } catch (IOException e) { - progressNotify( - destination, p.getIuid(), p.getCuid(), true, streamSCU.getNumberOfSuboperations()); - monitor( - sourceNode.getId(), - destination.getId(), - attributesOriginal, - attributesToSend, - false, - e.getMessage()); - throw e; - } catch (Exception e) { - if (e instanceof InterruptedException) { - Thread.currentThread().interrupt(); - } - progressNotify( - destination, p.getIuid(), p.getCuid(), true, streamSCU.getNumberOfSuboperations()); - monitor( - sourceNode.getId(), - destination.getId(), - attributesOriginal, - attributesToSend, - false, - e.getMessage()); - LOGGER.error(ERROR_WHEN_FORWARDING, e); - } finally { - streamSCU.triggerCloseExecutor(); - files = cleanOrGetBulkDataFiles(in, copy == null); - } - return files; - } - - private static Editable transformImage( - Attributes attributes, AttributeEditorContext context) { - MaskArea m = context.getMaskArea(); - boolean defacing = - LangUtil.getEmptytoFalse(context.getProperties().getProperty(Defacer.APPLY_DEFACING)); - if (m != null || defacing) { - return img -> { - PlanarImage image = img; - if (defacing) { - image = Defacer.apply(attributes, image); - } - if (m != null) { - image = MaskArea.drawShape(image.toMat(), m); - } - return image; - }; - } - return null; - } - - private static List cleanOrGetBulkDataFiles(DicomInputStream in, boolean clean) { - FileUtil.safeClose(in); - if (clean) { - // Force to clean if tmp bulk files - ServiceUtil.safeClose(in); - } else if (in != null) { - // Return tmp bulk files - return in.getBulkDataFiles(); - } - return null; - } - - public void transferOther( - ForwardDicomNode fwdNode, DicomForwardDestination destination, Attributes copy, Params p) - throws IOException { - StoreFromStreamSCU streamSCU = destination.getStreamSCU(); - Attributes attributesToSend = new Attributes(); - Attributes attributesOriginal = new Attributes(); - try { - if (!streamSCU.isReadyForDataTransfer()) { - throw new IllegalStateException("Association not ready for transfer."); - } - - DataWriter dataWriter; - String tsuid = p.getTsuid(); - String iuid = p.getIuid(); - String cuid = p.getCuid(); - var syntax = - new AdaptTransferSyntax( - tsuid, - streamSCU.selectTransferSyntax(cuid, destination.getOutputTransferSyntax(tsuid))); - List editors = destination.getDicomEditors(); - if (editors.isEmpty() && syntax.getRequested().equals(tsuid)) { - dataWriter = new DataWriterAdapter(copy); - attributesOriginal.addAll(copy); - attributesToSend = copy; - } else { - AttributeEditorContext context = - new AttributeEditorContext(tsuid, fwdNode, streamSCU.getRemoteDicomNode()); - Attributes attributes = new Attributes(copy); - attributesOriginal.addAll(attributes); - attributesToSend = attributes; - if (!editors.isEmpty()) { - editors.forEach(e -> e.apply(attributes, context)); - iuid = attributes.getString(Tag.SOPInstanceUID); - cuid = attributes.getString(Tag.SOPClassUID); - } - - if (context.getAbort() == Abort.FILE_EXCEPTION) { - throw new AbortException(context.getAbort(), context.getAbortMessage()); - } else if (context.getAbort() == Abort.CONNECTION_EXCEPTION) { - throw new AbortException( - context.getAbort(), "DICOM association abort. " + context.getAbortMessage()); - } - - BytesWithImageDescriptor desc = ImageAdapter.imageTranscode(attributes, syntax, context); - Editable editable = transformImage(attributes, context); - dataWriter = ImageAdapter.buildDataWriter(attributes, syntax, editable, desc); - } - - streamSCU.cstore(cuid, iuid, p.getPriority(), dataWriter, syntax.getSuitable()); - progressNotify( - destination, p.getIuid(), p.getCuid(), false, streamSCU.getNumberOfSuboperations()); - monitor( - fwdNode.getId(), destination.getId(), attributesOriginal, attributesToSend, true, null); - } catch (AbortException e) { - progressNotify( - destination, p.getIuid(), p.getCuid(), true, streamSCU.getNumberOfSuboperations()); - monitor( - fwdNode.getId(), - destination.getId(), - attributesOriginal, - attributesToSend, - false, - e.getMessage()); - if (e.getAbort() == Abort.CONNECTION_EXCEPTION) { - throw e; - } - } catch (IOException e) { - progressNotify( - destination, p.getIuid(), p.getCuid(), true, streamSCU.getNumberOfSuboperations()); - monitor( - fwdNode.getId(), - destination.getId(), - attributesOriginal, - attributesToSend, - false, - e.getMessage()); - throw e; - } catch (Exception e) { - if (e instanceof InterruptedException) { - Thread.currentThread().interrupt(); - } - progressNotify( - destination, p.getIuid(), p.getCuid(), true, streamSCU.getNumberOfSuboperations()); - monitor( - fwdNode.getId(), - destination.getId(), - attributesOriginal, - attributesToSend, - false, - e.getMessage()); - LOGGER.error(ERROR_WHEN_FORWARDING, e); - } finally { - streamSCU.triggerCloseExecutor(); - } - } - - public List transfer( - ForwardDicomNode fwdNode, WebForwardDestination destination, Attributes copy, Params p) - throws IOException { - DicomInputStream in = null; - List files; - Attributes attributesToSend = new Attributes(); - Attributes attributesOriginal = new Attributes(); - try { - List editors = destination.getDicomEditors(); - DicomStowRS stow = destination.getStowrsSingleFile(); - var syntax = - new AdaptTransferSyntax(p.getTsuid(), destination.getOutputTransferSyntax(p.getTsuid())); - - if (syntax.getRequested().equals(p.getTsuid()) && copy == null && editors.isEmpty()) { - Attributes fmi = - Attributes.createFileMetaInformation(p.getIuid(), p.getCuid(), syntax.getRequested()); - try (InputStream stream = p.getData()) { - attributesToSend = new DicomInputStream(p.getData()).readDataset(); - attributesOriginal.addAll(attributesToSend); - stow.uploadDicom(stream, fmi); - } catch (HttpException httpException) { - if (httpException.getStatusCode() != 409) { - throw new AbortException(Abort.FILE_EXCEPTION, httpException.getMessage()); - } else { - LOGGER.debug("File already present in destination"); - } - } - } else { - AttributeEditorContext context = new AttributeEditorContext(p.getTsuid(), fwdNode, null); - in = new DicomInputStream(p.getData(), p.getTsuid()); - in.setIncludeBulkData(IncludeBulkData.URI); - Attributes attributes = in.readDataset(); - attributesToSend = attributes; - attributesOriginal.addAll(attributes); - if (copy != null) { - copy.addAll(attributes); - } - if (!editors.isEmpty()) { - editors.forEach(e -> e.apply(attributes, context)); - } - - if (context.getAbort() == Abort.FILE_EXCEPTION) { - if (p.getData() instanceof PDVInputStream) { - ((PDVInputStream) p.getData()).skipAll(); - } - throw new AbortException(context.getAbort(), context.getAbortMessage()); - } else if (context.getAbort() == Abort.CONNECTION_EXCEPTION) { - if (p.getAs() != null) { - p.getAs().abort(); - } - throw new AbortException( - context.getAbort(), "STOW-RS abort: " + context.getAbortMessage()); - } - - BytesWithImageDescriptor desc = ImageAdapter.imageTranscode(attributes, syntax, context); - if (desc == null) { - stow.uploadDicom(attributes, syntax.getOriginal()); - } else { - Editable editable = transformImage(attributes, context); - stow.uploadPayload(ImageAdapter.preparePlayload(attributes, syntax, desc, editable)); - } - } - progressNotify(destination, p.getIuid(), p.getCuid(), false, 0); - monitor( - fwdNode.getId(), destination.getId(), attributesOriginal, attributesToSend, true, null); - } catch (AbortException e) { - progressNotify(destination, p.getIuid(), p.getCuid(), true, 0); - monitor( - fwdNode.getId(), - destination.getId(), - attributesOriginal, - attributesToSend, - false, - e.getMessage()); - if (e.getAbort() == Abort.CONNECTION_EXCEPTION) { - throw e; - } - } catch (IOException e) { - progressNotify(destination, p.getIuid(), p.getCuid(), true, 0); - monitor( - fwdNode.getId(), - destination.getId(), - attributesOriginal, - attributesToSend, - false, - e.getMessage()); - throw e; - } catch (Exception e) { - progressNotify(destination, p.getIuid(), p.getCuid(), true, 0); - monitor( - fwdNode.getId(), - destination.getId(), - attributesOriginal, - attributesToSend, - false, - e.getMessage()); - LOGGER.error(ERROR_WHEN_FORWARDING, e); - } finally { - files = cleanOrGetBulkDataFiles(in, copy == null); - } - return files; - } - - public void transferOther( - ForwardDicomNode fwdNode, WebForwardDestination destination, Attributes copy, Params p) - throws IOException { - Attributes attributesToSend = new Attributes(); - Attributes attributesOriginal = new Attributes(); - try { - List editors = destination.getDicomEditors(); - DicomStowRS stow = destination.getStowrsSingleFile(); - var syntax = - new AdaptTransferSyntax(p.getTsuid(), destination.getOutputTransferSyntax(p.getTsuid())); - if (syntax.getRequested().equals(p.getTsuid()) && editors.isEmpty()) { - attributesToSend = copy; - attributesOriginal.addAll(copy); - stow.uploadDicom(copy, syntax.getRequested()); - } else { - AttributeEditorContext context = new AttributeEditorContext(p.getTsuid(), fwdNode, null); - Attributes attributes = new Attributes(copy); - attributesToSend = attributes; - attributesOriginal.addAll(attributes); - editors.forEach(e -> e.apply(attributes, context)); - - if (context.getAbort() == Abort.FILE_EXCEPTION) { - throw new AbortException(context.getAbort(), context.getAbortMessage()); - } else if (context.getAbort() == Abort.CONNECTION_EXCEPTION) { - throw new AbortException( - context.getAbort(), "DICOM associtation abort. " + context.getAbortMessage()); - } - - BytesWithImageDescriptor desc = ImageAdapter.imageTranscode(attributes, syntax, context); - if (desc == null) { - stow.uploadDicom(attributes, syntax.getOriginal()); - } else { - Editable editable = transformImage(attributes, context); - stow.uploadPayload(ImageAdapter.preparePlayload(attributes, syntax, desc, editable)); - } - progressNotify(destination, p.getIuid(), p.getCuid(), false, 0); - monitor( - fwdNode.getId(), destination.getId(), attributesOriginal, attributesToSend, true, null); - } - } catch (HttpException httpException) { - if (httpException.getStatusCode() != 409) { - progressNotify(destination, p.getIuid(), p.getCuid(), true, 0); - monitor( - fwdNode.getId(), - destination.getId(), - attributesOriginal, - attributesToSend, - false, - httpException.getMessage()); - throw new AbortException(Abort.FILE_EXCEPTION, "DICOMWeb forward", httpException); - } else { - progressNotify(destination, p.getIuid(), p.getCuid(), false, 0); - monitor( - fwdNode.getId(), destination.getId(), attributesOriginal, attributesToSend, true, null); - LOGGER.debug("File already present in destination"); - } - } catch (AbortException e) { - progressNotify(destination, p.getIuid(), p.getCuid(), true, 0); - monitor( - fwdNode.getId(), - destination.getId(), - attributesOriginal, - attributesToSend, - false, - e.getMessage()); - if (e.getAbort() == Abort.CONNECTION_EXCEPTION) { - throw e; - } - } catch (IOException e) { - progressNotify(destination, p.getIuid(), p.getCuid(), true, 0); - monitor( - fwdNode.getId(), - destination.getId(), - attributesOriginal, - attributesToSend, - false, - e.getMessage()); - throw e; - } catch (Exception e) { - progressNotify(destination, p.getIuid(), p.getCuid(), true, 0); - monitor( - fwdNode.getId(), - destination.getId(), - attributesOriginal, - attributesToSend, - false, - e.getMessage()); - LOGGER.error(ERROR_WHEN_FORWARDING, e); - } - } - - private static void progressNotify( - ForwardDestination destination, String iuid, String cuid, boolean failed, int subOperations) { - ServiceUtil.notifyProgession( - destination.getState(), - iuid, - cuid, - failed ? Status.ProcessingFailure : Status.Success, - failed ? ProgressStatus.FAILED : ProgressStatus.COMPLETED, - subOperations); - } - - public static String selectTransferSyntax(Association as, String cuid, String filets) { - Set tss = as.getTransferSyntaxesFor(cuid); - if (tss.contains(filets)) { - return filets; - } - - if (tss.contains(UID.ExplicitVRLittleEndian)) { - return UID.ExplicitVRLittleEndian; - } - - return UID.ImplicitVRLittleEndian; - } - - /** - * Publish an event for monitoring purpose - * - * @param forwardNodeId ForwardNode Id - * @param destinationId Destination Id - * @param attributesOriginal Original value - * @param attributesToSend De-identify value - * @param sent Flag to know if the transfer occurred - * @param reason Reason of not transferring the file - */ - private void monitor( - Long forwardNodeId, - Long destinationId, - Attributes attributesOriginal, - Attributes attributesToSend, - boolean sent, - String reason) { - applicationEventPublisher.publishEvent( - new TransferMonitoringEvent( - TransferStatusEntity.buildTransferStatusEntity( - forwardNodeId, destinationId, attributesOriginal, attributesToSend, sent, reason))); - } + private static final String ERROR_WHEN_FORWARDING = "Error when forwarding to the final destination"; + + private static final Logger LOGGER = LoggerFactory.getLogger(ForwardService.class); + + private final ApplicationEventPublisher applicationEventPublisher; + + @Autowired + public ForwardService(final ApplicationEventPublisher applicationEventPublisher) { + this.applicationEventPublisher = applicationEventPublisher; + } + + public void storeMultipleDestination(ForwardDicomNode fwdNode, List destList, Params p) + throws IOException { + if (destList == null || destList.isEmpty()) { + throw new IllegalStateException("Cannot find the DICOM destination from " + fwdNode.toString()); + } + // Exclude DICOMDIR + if ("1.2.840.10008.1.3.10".equals(p.getCuid())) { + LOGGER.warn("Cannot send DICOMDIR {}", p.getIuid()); + return; + } + + if (destList.size() == 1) { + storeOneDestination(fwdNode, destList.get(0), p); + } + else { + List destConList = new ArrayList<>(); + for (ForwardDestination fwDest : destList) { + try { + if (fwDest instanceof DicomForwardDestination) { + prepareTransfer((DicomForwardDestination) fwDest, p); + } + destConList.add(fwDest); + } + catch (Exception e) { + LOGGER.error("Cannot connect to the final destination", e); + } + } + + if (destConList.isEmpty()) { + return; + } + else if (destConList.size() == 1) { + storeOneDestination(fwdNode, destConList.get(0), p); + } + else { + List files = null; + try { + Attributes attributes = new Attributes(); + ForwardDestination fistDest = destConList.get(0); + if (fistDest instanceof DicomForwardDestination) { + files = transfer(fwdNode, (DicomForwardDestination) fistDest, attributes, p); + } + else if (fistDest instanceof WebForwardDestination) { + files = transfer(fwdNode, (WebForwardDestination) fistDest, attributes, p); + } + if (!attributes.isEmpty()) { + for (int i = 1; i < destConList.size(); i++) { + ForwardDestination dest = destConList.get(i); + if (dest instanceof DicomForwardDestination) { + transferOther(fwdNode, (DicomForwardDestination) dest, attributes, p); + } + else if (dest instanceof WebForwardDestination) { + transferOther(fwdNode, (WebForwardDestination) dest, attributes, p); + } + } + } + } + finally { + if (files != null) { + // Force to clean if tmp bulk files + for (File file : files) { + FileUtil.delete(file); + } + } + } + } + } + } + + public void storeOneDestination(ForwardDicomNode fwdNode, ForwardDestination destination, Params p) + throws IOException { + if (destination instanceof DicomForwardDestination) { + DicomForwardDestination dest = (DicomForwardDestination) destination; + prepareTransfer(dest, p); + transfer(fwdNode, dest, null, p); + } + else if (destination instanceof WebForwardDestination) { + transfer(fwdNode, (WebForwardDestination) destination, null, p); + } + } + + public static synchronized StoreFromStreamSCU prepareTransfer(DicomForwardDestination destination, Params p) + throws IOException { + String cuid = p.getCuid(); + String tsuid = p.getTsuid(); + String dstTsuid = destination.getOutputTransferSyntax(tsuid); + StoreFromStreamSCU streamSCU = destination.getStreamSCU(); + + if (streamSCU.hasAssociation()) { + // Handle dynamically new SOPClassUID + Set tss = streamSCU.getTransferSyntaxesFor(cuid); + if (!tss.contains(dstTsuid)) { + streamSCU.close(true); + } + + // Add Presentation Context for the association + streamSCU.addData(cuid, dstTsuid); + if (DicomOutputData.isAdaptableSyntax(dstTsuid)) { + streamSCU.addData(cuid, UID.JPEGLosslessSV1); + } + + if (!streamSCU.isReadyForDataTransfer()) { + // If connection has been closed just reopen + streamSCU.open(); + } + } + else { + destination.getStreamSCUService().start(); + // Add Presentation Context for the association + streamSCU.addData(cuid, dstTsuid); + if (!dstTsuid.equals(UID.ExplicitVRLittleEndian)) { + streamSCU.addData(cuid, UID.ExplicitVRLittleEndian); + } + if (DicomOutputData.isAdaptableSyntax(dstTsuid)) { + streamSCU.addData(cuid, UID.JPEGLosslessSV1); + } + streamSCU.open(); + } + return streamSCU; + } + + public List transfer(ForwardDicomNode sourceNode, DicomForwardDestination destination, Attributes copy, + Params p) throws IOException { + StoreFromStreamSCU streamSCU = destination.getStreamSCU(); + DicomInputStream in = null; + List files; + Attributes attributesOriginal = new Attributes(); + Attributes attributesToSend = new Attributes(); + try { + if (!streamSCU.isReadyForDataTransfer()) { + throw new IllegalStateException("Association not ready for transfer."); + } + DataWriter dataWriter; + String cuid = p.getCuid(); + String iuid = p.getIuid(); + String tsuid = p.getTsuid(); + var syntax = new AdaptTransferSyntax(tsuid, + streamSCU.selectTransferSyntax(cuid, destination.getOutputTransferSyntax(tsuid))); + List editors = destination.getDicomEditors(); + + if (copy == null && editors.isEmpty() && syntax.getRequested().equals(tsuid)) { + dataWriter = new InputStreamDataWriter(p.getData()); + attributesToSend = new DicomInputStream(p.getData()).readDataset(); + attributesOriginal.addAll(attributesToSend); + } + else { + AttributeEditorContext context = new AttributeEditorContext(tsuid, sourceNode, + streamSCU.getRemoteDicomNode()); + in = new DicomInputStream(p.getData(), tsuid); + in.setIncludeBulkData(IncludeBulkData.URI); + Attributes attributes = in.readDataset(); + attributesOriginal.addAll(attributes); + attributesToSend = attributes; + if (copy != null) { + copy.addAll(attributes); + } + + if (!editors.isEmpty()) { + editors.forEach(e -> e.apply(attributes, context)); + iuid = attributes.getString(Tag.SOPInstanceUID); + cuid = attributes.getString(Tag.SOPClassUID); + } + + if (context.getAbort() == Abort.FILE_EXCEPTION) { + if (p.getData() instanceof PDVInputStream) { + ((PDVInputStream) p.getData()).skipAll(); + } + throw new AbortException(context.getAbort(), context.getAbortMessage()); + } + else if (context.getAbort() == Abort.CONNECTION_EXCEPTION) { + if (p.getAs() != null) { + p.getAs().abort(); + } + throw new AbortException(context.getAbort(), + "DICOM association abort: " + context.getAbortMessage()); + } + + BytesWithImageDescriptor desc = ImageAdapter.imageTranscode(attributes, syntax, context); + Editable editable = transformImage(attributes, context); + dataWriter = ImageAdapter.buildDataWriter(attributes, syntax, editable, desc); + } + + streamSCU.cstore(cuid, iuid, p.getPriority(), dataWriter, syntax.getSuitable()); + progressNotify(destination, p.getIuid(), p.getCuid(), false, streamSCU.getNumberOfSuboperations()); + monitor(sourceNode.getId(), destination.getId(), attributesOriginal, attributesToSend, true, null); + } + catch (AbortException e) { + progressNotify(destination, p.getIuid(), p.getCuid(), true, streamSCU.getNumberOfSuboperations()); + monitor(sourceNode.getId(), destination.getId(), attributesOriginal, attributesToSend, false, + e.getMessage()); + if (e.getAbort() == Abort.CONNECTION_EXCEPTION) { + throw e; + } + } + catch (IOException e) { + progressNotify(destination, p.getIuid(), p.getCuid(), true, streamSCU.getNumberOfSuboperations()); + monitor(sourceNode.getId(), destination.getId(), attributesOriginal, attributesToSend, false, + e.getMessage()); + throw e; + } + catch (Exception e) { + if (e instanceof InterruptedException) { + Thread.currentThread().interrupt(); + } + progressNotify(destination, p.getIuid(), p.getCuid(), true, streamSCU.getNumberOfSuboperations()); + monitor(sourceNode.getId(), destination.getId(), attributesOriginal, attributesToSend, false, + e.getMessage()); + LOGGER.error(ERROR_WHEN_FORWARDING, e); + } + finally { + streamSCU.triggerCloseExecutor(); + files = cleanOrGetBulkDataFiles(in, copy == null); + } + return files; + } + + private static Editable transformImage(Attributes attributes, AttributeEditorContext context) { + MaskArea m = context.getMaskArea(); + boolean defacing = LangUtil.getEmptytoFalse(context.getProperties().getProperty(Defacer.APPLY_DEFACING)); + if (m != null || defacing) { + return img -> { + PlanarImage image = img; + if (defacing) { + image = Defacer.apply(attributes, image); + } + if (m != null) { + image = MaskArea.drawShape(image.toMat(), m); + } + return image; + }; + } + return null; + } + + private static List cleanOrGetBulkDataFiles(DicomInputStream in, boolean clean) { + FileUtil.safeClose(in); + if (clean) { + // Force to clean if tmp bulk files + ServiceUtil.safeClose(in); + } + else if (in != null) { + // Return tmp bulk files + return in.getBulkDataFiles(); + } + return null; + } + + public void transferOther(ForwardDicomNode fwdNode, DicomForwardDestination destination, Attributes copy, Params p) + throws IOException { + StoreFromStreamSCU streamSCU = destination.getStreamSCU(); + Attributes attributesToSend = new Attributes(); + Attributes attributesOriginal = new Attributes(); + try { + if (!streamSCU.isReadyForDataTransfer()) { + throw new IllegalStateException("Association not ready for transfer."); + } + + DataWriter dataWriter; + String tsuid = p.getTsuid(); + String iuid = p.getIuid(); + String cuid = p.getCuid(); + var syntax = new AdaptTransferSyntax(tsuid, + streamSCU.selectTransferSyntax(cuid, destination.getOutputTransferSyntax(tsuid))); + List editors = destination.getDicomEditors(); + if (editors.isEmpty() && syntax.getRequested().equals(tsuid)) { + dataWriter = new DataWriterAdapter(copy); + attributesOriginal.addAll(copy); + attributesToSend = copy; + } + else { + AttributeEditorContext context = new AttributeEditorContext(tsuid, fwdNode, + streamSCU.getRemoteDicomNode()); + Attributes attributes = new Attributes(copy); + attributesOriginal.addAll(attributes); + attributesToSend = attributes; + if (!editors.isEmpty()) { + editors.forEach(e -> e.apply(attributes, context)); + iuid = attributes.getString(Tag.SOPInstanceUID); + cuid = attributes.getString(Tag.SOPClassUID); + } + + if (context.getAbort() == Abort.FILE_EXCEPTION) { + throw new AbortException(context.getAbort(), context.getAbortMessage()); + } + else if (context.getAbort() == Abort.CONNECTION_EXCEPTION) { + throw new AbortException(context.getAbort(), + "DICOM association abort. " + context.getAbortMessage()); + } + + BytesWithImageDescriptor desc = ImageAdapter.imageTranscode(attributes, syntax, context); + Editable editable = transformImage(attributes, context); + dataWriter = ImageAdapter.buildDataWriter(attributes, syntax, editable, desc); + } + + streamSCU.cstore(cuid, iuid, p.getPriority(), dataWriter, syntax.getSuitable()); + progressNotify(destination, p.getIuid(), p.getCuid(), false, streamSCU.getNumberOfSuboperations()); + monitor(fwdNode.getId(), destination.getId(), attributesOriginal, attributesToSend, true, null); + } + catch (AbortException e) { + progressNotify(destination, p.getIuid(), p.getCuid(), true, streamSCU.getNumberOfSuboperations()); + monitor(fwdNode.getId(), destination.getId(), attributesOriginal, attributesToSend, false, e.getMessage()); + if (e.getAbort() == Abort.CONNECTION_EXCEPTION) { + throw e; + } + } + catch (IOException e) { + progressNotify(destination, p.getIuid(), p.getCuid(), true, streamSCU.getNumberOfSuboperations()); + monitor(fwdNode.getId(), destination.getId(), attributesOriginal, attributesToSend, false, e.getMessage()); + throw e; + } + catch (Exception e) { + if (e instanceof InterruptedException) { + Thread.currentThread().interrupt(); + } + progressNotify(destination, p.getIuid(), p.getCuid(), true, streamSCU.getNumberOfSuboperations()); + monitor(fwdNode.getId(), destination.getId(), attributesOriginal, attributesToSend, false, e.getMessage()); + LOGGER.error(ERROR_WHEN_FORWARDING, e); + } + finally { + streamSCU.triggerCloseExecutor(); + } + } + + public List transfer(ForwardDicomNode fwdNode, WebForwardDestination destination, Attributes copy, Params p) + throws IOException { + DicomInputStream in = null; + List files; + Attributes attributesToSend = new Attributes(); + Attributes attributesOriginal = new Attributes(); + try { + List editors = destination.getDicomEditors(); + DicomStowRS stow = destination.getStowrsSingleFile(); + var syntax = new AdaptTransferSyntax(p.getTsuid(), destination.getOutputTransferSyntax(p.getTsuid())); + + if (syntax.getRequested().equals(p.getTsuid()) && copy == null && editors.isEmpty()) { + Attributes fmi = Attributes.createFileMetaInformation(p.getIuid(), p.getCuid(), syntax.getRequested()); + try (InputStream stream = p.getData()) { + attributesToSend = new DicomInputStream(p.getData()).readDataset(); + attributesOriginal.addAll(attributesToSend); + stow.uploadDicom(stream, fmi); + } + catch (HttpException httpException) { + if (httpException.getStatusCode() != 409) { + throw new AbortException(Abort.FILE_EXCEPTION, httpException.getMessage()); + } + else { + LOGGER.debug("File already present in destination"); + } + } + } + else { + AttributeEditorContext context = new AttributeEditorContext(p.getTsuid(), fwdNode, null); + in = new DicomInputStream(p.getData(), p.getTsuid()); + in.setIncludeBulkData(IncludeBulkData.URI); + Attributes attributes = in.readDataset(); + attributesToSend = attributes; + attributesOriginal.addAll(attributes); + if (copy != null) { + copy.addAll(attributes); + } + if (!editors.isEmpty()) { + editors.forEach(e -> e.apply(attributes, context)); + } + + if (context.getAbort() == Abort.FILE_EXCEPTION) { + if (p.getData() instanceof PDVInputStream) { + ((PDVInputStream) p.getData()).skipAll(); + } + throw new AbortException(context.getAbort(), context.getAbortMessage()); + } + else if (context.getAbort() == Abort.CONNECTION_EXCEPTION) { + if (p.getAs() != null) { + p.getAs().abort(); + } + throw new AbortException(context.getAbort(), "STOW-RS abort: " + context.getAbortMessage()); + } + + BytesWithImageDescriptor desc = ImageAdapter.imageTranscode(attributes, syntax, context); + if (desc == null) { + stow.uploadDicom(attributes, syntax.getOriginal()); + } + else { + Editable editable = transformImage(attributes, context); + stow.uploadPayload(ImageAdapter.preparePlayload(attributes, syntax, desc, editable)); + } + } + progressNotify(destination, p.getIuid(), p.getCuid(), false, 0); + monitor(fwdNode.getId(), destination.getId(), attributesOriginal, attributesToSend, true, null); + } + catch (AbortException e) { + progressNotify(destination, p.getIuid(), p.getCuid(), true, 0); + monitor(fwdNode.getId(), destination.getId(), attributesOriginal, attributesToSend, false, e.getMessage()); + if (e.getAbort() == Abort.CONNECTION_EXCEPTION) { + throw e; + } + } + catch (IOException e) { + progressNotify(destination, p.getIuid(), p.getCuid(), true, 0); + monitor(fwdNode.getId(), destination.getId(), attributesOriginal, attributesToSend, false, e.getMessage()); + throw e; + } + catch (Exception e) { + progressNotify(destination, p.getIuid(), p.getCuid(), true, 0); + monitor(fwdNode.getId(), destination.getId(), attributesOriginal, attributesToSend, false, e.getMessage()); + LOGGER.error(ERROR_WHEN_FORWARDING, e); + } + finally { + files = cleanOrGetBulkDataFiles(in, copy == null); + } + return files; + } + + public void transferOther(ForwardDicomNode fwdNode, WebForwardDestination destination, Attributes copy, Params p) + throws IOException { + Attributes attributesToSend = new Attributes(); + Attributes attributesOriginal = new Attributes(); + try { + List editors = destination.getDicomEditors(); + DicomStowRS stow = destination.getStowrsSingleFile(); + var syntax = new AdaptTransferSyntax(p.getTsuid(), destination.getOutputTransferSyntax(p.getTsuid())); + if (syntax.getRequested().equals(p.getTsuid()) && editors.isEmpty()) { + attributesToSend = copy; + attributesOriginal.addAll(copy); + stow.uploadDicom(copy, syntax.getRequested()); + } + else { + AttributeEditorContext context = new AttributeEditorContext(p.getTsuid(), fwdNode, null); + Attributes attributes = new Attributes(copy); + attributesToSend = attributes; + attributesOriginal.addAll(attributes); + editors.forEach(e -> e.apply(attributes, context)); + + if (context.getAbort() == Abort.FILE_EXCEPTION) { + throw new AbortException(context.getAbort(), context.getAbortMessage()); + } + else if (context.getAbort() == Abort.CONNECTION_EXCEPTION) { + throw new AbortException(context.getAbort(), + "DICOM associtation abort. " + context.getAbortMessage()); + } + + BytesWithImageDescriptor desc = ImageAdapter.imageTranscode(attributes, syntax, context); + if (desc == null) { + stow.uploadDicom(attributes, syntax.getOriginal()); + } + else { + Editable editable = transformImage(attributes, context); + stow.uploadPayload(ImageAdapter.preparePlayload(attributes, syntax, desc, editable)); + } + progressNotify(destination, p.getIuid(), p.getCuid(), false, 0); + monitor(fwdNode.getId(), destination.getId(), attributesOriginal, attributesToSend, true, null); + } + } + catch (HttpException httpException) { + if (httpException.getStatusCode() != 409) { + progressNotify(destination, p.getIuid(), p.getCuid(), true, 0); + monitor(fwdNode.getId(), destination.getId(), attributesOriginal, attributesToSend, false, + httpException.getMessage()); + throw new AbortException(Abort.FILE_EXCEPTION, "DICOMWeb forward", httpException); + } + else { + progressNotify(destination, p.getIuid(), p.getCuid(), false, 0); + monitor(fwdNode.getId(), destination.getId(), attributesOriginal, attributesToSend, true, null); + LOGGER.debug("File already present in destination"); + } + } + catch (AbortException e) { + progressNotify(destination, p.getIuid(), p.getCuid(), true, 0); + monitor(fwdNode.getId(), destination.getId(), attributesOriginal, attributesToSend, false, e.getMessage()); + if (e.getAbort() == Abort.CONNECTION_EXCEPTION) { + throw e; + } + } + catch (IOException e) { + progressNotify(destination, p.getIuid(), p.getCuid(), true, 0); + monitor(fwdNode.getId(), destination.getId(), attributesOriginal, attributesToSend, false, e.getMessage()); + throw e; + } + catch (Exception e) { + progressNotify(destination, p.getIuid(), p.getCuid(), true, 0); + monitor(fwdNode.getId(), destination.getId(), attributesOriginal, attributesToSend, false, e.getMessage()); + LOGGER.error(ERROR_WHEN_FORWARDING, e); + } + } + + private static void progressNotify(ForwardDestination destination, String iuid, String cuid, boolean failed, + int subOperations) { + ServiceUtil.notifyProgession(destination.getState(), iuid, cuid, + failed ? Status.ProcessingFailure : Status.Success, + failed ? ProgressStatus.FAILED : ProgressStatus.COMPLETED, subOperations); + } + + public static String selectTransferSyntax(Association as, String cuid, String filets) { + Set tss = as.getTransferSyntaxesFor(cuid); + if (tss.contains(filets)) { + return filets; + } + + if (tss.contains(UID.ExplicitVRLittleEndian)) { + return UID.ExplicitVRLittleEndian; + } + + return UID.ImplicitVRLittleEndian; + } + + /** + * Publish an event for monitoring purpose + * @param forwardNodeId ForwardNode Id + * @param destinationId Destination Id + * @param attributesOriginal Original value + * @param attributesToSend De-identify value + * @param sent Flag to know if the transfer occurred + * @param reason Reason of not transferring the file + */ + private void monitor(Long forwardNodeId, Long destinationId, Attributes attributesOriginal, + Attributes attributesToSend, boolean sent, String reason) { + applicationEventPublisher + .publishEvent(new TransferMonitoringEvent(TransferStatusEntity.buildTransferStatusEntity(forwardNodeId, + destinationId, attributesOriginal, attributesToSend, sent, reason))); + } + } diff --git a/src/main/java/org/karnak/backend/service/HazelcastService.java b/src/main/java/org/karnak/backend/service/HazelcastService.java index f520188f0..1131b4cc4 100644 --- a/src/main/java/org/karnak/backend/service/HazelcastService.java +++ b/src/main/java/org/karnak/backend/service/HazelcastService.java @@ -19,17 +19,14 @@ @Service public class HazelcastService { - private static final Logger LOGGER = LoggerFactory.getLogger(HazelcastService.class); + private static final Logger LOGGER = LoggerFactory.getLogger(HazelcastService.class); + + /** Log every minutes */ + @Scheduled(fixedRate = 60000) + public void logHazelcast() { + LOGGER.info(String.format("Hazelcast values for instance %s:%s", AppConfig.getInstance().getNameInstance(), + AppConfig.getInstance().getExternalIDCache().getAll().stream().map(Object::toString) + .collect(Collectors.joining("***")))); + } - /** Log every minutes */ - @Scheduled(fixedRate = 60000) - public void logHazelcast() { - LOGGER.info( - String.format( - "Hazelcast values for instance %s:%s", - AppConfig.getInstance().getNameInstance(), - AppConfig.getInstance().getExternalIDCache().getAll().stream() - .map(Object::toString) - .collect(Collectors.joining("***")))); - } } diff --git a/src/main/java/org/karnak/backend/service/KheopsAlbumsService.java b/src/main/java/org/karnak/backend/service/KheopsAlbumsService.java index 4c83836de..065d63a2c 100644 --- a/src/main/java/org/karnak/backend/service/KheopsAlbumsService.java +++ b/src/main/java/org/karnak/backend/service/KheopsAlbumsService.java @@ -21,90 +21,80 @@ @Service public class KheopsAlbumsService { - private final KheopsAlbumsRepo kheopsAlbumsRepo; + private final KheopsAlbumsRepo kheopsAlbumsRepo; - @Autowired - public KheopsAlbumsService(final KheopsAlbumsRepo kheopsAlbumsRepo) { - this.kheopsAlbumsRepo = kheopsAlbumsRepo; - } + @Autowired + public KheopsAlbumsService(final KheopsAlbumsRepo kheopsAlbumsRepo) { + this.kheopsAlbumsRepo = kheopsAlbumsRepo; + } - public void newSwitchingAlbum(KheopsAlbumsEntity kheopsAlbum) { - Long destinationID = - kheopsAlbum.getDestinationEntity() != null - ? kheopsAlbum.getDestinationEntity().getId() - : null; - if (destinationID != null) { - kheopsAlbumsRepo.saveAndFlush(kheopsAlbum); - } - } + public void newSwitchingAlbum(KheopsAlbumsEntity kheopsAlbum) { + Long destinationID = kheopsAlbum.getDestinationEntity() != null ? kheopsAlbum.getDestinationEntity().getId() + : null; + if (destinationID != null) { + kheopsAlbumsRepo.saveAndFlush(kheopsAlbum); + } + } - public void updateSwitchingAlbumsFromDestination(DestinationEntity destinationEntity) { - if (destinationEntity.getKheopsAlbumEntities() != null) { - for (KheopsAlbumsEntity kheopsAlbum : destinationEntity.getKheopsAlbumEntities()) { - setDestination(destinationEntity, kheopsAlbum); - } - } - removeKheopsAlbums(destinationEntity); - } + public void updateSwitchingAlbumsFromDestination(DestinationEntity destinationEntity) { + if (destinationEntity.getKheopsAlbumEntities() != null) { + for (KheopsAlbumsEntity kheopsAlbum : destinationEntity.getKheopsAlbumEntities()) { + setDestination(destinationEntity, kheopsAlbum); + } + } + removeKheopsAlbums(destinationEntity); + } - private void removeKheopsAlbums(DestinationEntity destinationEntity) { - List kheopsAlbumsEntityListDatabase = new ArrayList<>(); - kheopsAlbumsRepo - .findAllByDestinationEntity(destinationEntity) // - .forEach(kheopsAlbumsEntityListDatabase::add); - deleteDiffCurrentAndDatabase(destinationEntity, kheopsAlbumsEntityListDatabase); - deleteAll(destinationEntity, kheopsAlbumsEntityListDatabase); - } + private void removeKheopsAlbums(DestinationEntity destinationEntity) { + List kheopsAlbumsEntityListDatabase = new ArrayList<>(); + kheopsAlbumsRepo.findAllByDestinationEntity(destinationEntity) // + .forEach(kheopsAlbumsEntityListDatabase::add); + deleteDiffCurrentAndDatabase(destinationEntity, kheopsAlbumsEntityListDatabase); + deleteAll(destinationEntity, kheopsAlbumsEntityListDatabase); + } - private void deleteDiffCurrentAndDatabase( - DestinationEntity destinationEntity, - List kheopsAlbumsEntityListDatabase) { - if (destinationEntity.getKheopsAlbumEntities() != null - && kheopsAlbumsEntityListDatabase != null - && destinationEntity.getKheopsAlbumEntities().size() - != kheopsAlbumsEntityListDatabase.size()) { - for (KheopsAlbumsEntity kheopsAlbumDatabase : kheopsAlbumsEntityListDatabase) { - Predicate idIsAlwaysPresent = - kheopsAlbum -> kheopsAlbum.getId().equals(kheopsAlbumDatabase.getId()); - if (!destinationEntity.getKheopsAlbumEntities().stream().anyMatch(idIsAlwaysPresent)) { - deleteSwitchingAlbums(kheopsAlbumDatabase); - } - } - } - } + private void deleteDiffCurrentAndDatabase(DestinationEntity destinationEntity, + List kheopsAlbumsEntityListDatabase) { + if (destinationEntity.getKheopsAlbumEntities() != null && kheopsAlbumsEntityListDatabase != null + && destinationEntity.getKheopsAlbumEntities().size() != kheopsAlbumsEntityListDatabase.size()) { + for (KheopsAlbumsEntity kheopsAlbumDatabase : kheopsAlbumsEntityListDatabase) { + Predicate idIsAlwaysPresent = kheopsAlbum -> kheopsAlbum.getId() + .equals(kheopsAlbumDatabase.getId()); + if (!destinationEntity.getKheopsAlbumEntities().stream().anyMatch(idIsAlwaysPresent)) { + deleteSwitchingAlbums(kheopsAlbumDatabase); + } + } + } + } - private void deleteAll( - DestinationEntity destinationEntity, - List kheopsAlbumsEntityListDatabase) { - if (destinationEntity.getKheopsAlbumEntities() == null - && kheopsAlbumsEntityListDatabase != null) { - deleteListSwitchingAlbums(kheopsAlbumsEntityListDatabase); - } - } + private void deleteAll(DestinationEntity destinationEntity, + List kheopsAlbumsEntityListDatabase) { + if (destinationEntity.getKheopsAlbumEntities() == null && kheopsAlbumsEntityListDatabase != null) { + deleteListSwitchingAlbums(kheopsAlbumsEntityListDatabase); + } + } - public void setDestination(DestinationEntity destinationEntity, KheopsAlbumsEntity kheopsAlbum) { - Long destinationID = - kheopsAlbum.getDestinationEntity() != null - ? kheopsAlbum.getDestinationEntity().getId() - : null; - if (destinationID == null) { - kheopsAlbum.setDestinationEntity(destinationEntity); - } - kheopsAlbumsRepo.saveAndFlush(kheopsAlbum); - } + public void setDestination(DestinationEntity destinationEntity, KheopsAlbumsEntity kheopsAlbum) { + Long destinationID = kheopsAlbum.getDestinationEntity() != null ? kheopsAlbum.getDestinationEntity().getId() + : null; + if (destinationID == null) { + kheopsAlbum.setDestinationEntity(destinationEntity); + } + kheopsAlbumsRepo.saveAndFlush(kheopsAlbum); + } - public void deleteSwitchingAlbums(KheopsAlbumsEntity kheopsAlbumsEntity) { - kheopsAlbumsRepo.deleteById(kheopsAlbumsEntity.getId()); - kheopsAlbumsRepo.flush(); - } + public void deleteSwitchingAlbums(KheopsAlbumsEntity kheopsAlbumsEntity) { + kheopsAlbumsRepo.deleteById(kheopsAlbumsEntity.getId()); + kheopsAlbumsRepo.flush(); + } + + public void deleteListSwitchingAlbums(List kheopsAlbumsEntityList) { + if (kheopsAlbumsEntityList != null) { + kheopsAlbumsEntityList.forEach(kheopsAlbums -> { + kheopsAlbumsRepo.deleteById(kheopsAlbums.getId()); + }); + kheopsAlbumsRepo.flush(); + } + } - public void deleteListSwitchingAlbums(List kheopsAlbumsEntityList) { - if (kheopsAlbumsEntityList != null) { - kheopsAlbumsEntityList.forEach( - kheopsAlbums -> { - kheopsAlbumsRepo.deleteById(kheopsAlbums.getId()); - }); - kheopsAlbumsRepo.flush(); - } - } } diff --git a/src/main/java/org/karnak/backend/service/NotificationService.java b/src/main/java/org/karnak/backend/service/NotificationService.java index d52047cc0..fc58e527e 100644 --- a/src/main/java/org/karnak/backend/service/NotificationService.java +++ b/src/main/java/org/karnak/backend/service/NotificationService.java @@ -43,467 +43,388 @@ @Service public class NotificationService { - private static final Logger LOGGER = LoggerFactory.getLogger(NotificationService.class); - - // Services - private final TemplateEngine templateEngine; - private final JavaMailSender javaMailSender; - - // Repositories - private final TransferStatusRepo transferStatusRepo; - private final DestinationRepo destinationRepo; - - @Autowired - public NotificationService( - final TemplateEngine templateEngine, - final JavaMailSender javaMailSender, - final TransferStatusRepo transferStatusRepo, - final DestinationRepo destinationRepo) { - this.templateEngine = templateEngine; - this.javaMailSender = javaMailSender; - this.transferStatusRepo = transferStatusRepo; - this.destinationRepo = destinationRepo; - } - - /** - * In a regular period of time, check for new inputs in the transfer notifications, build the - * notifications and send them via email. - */ - @Scheduled(fixedRate = 10 * 1000) - private void determineNotificationToSend() { - buildNotificationsToSend().forEach(this::prepareAndSendNotification); - } - - /** - * Build transfer notification to send - * - * @return notifications to send - */ - List buildNotificationsToSend() { - List transferMonitoringNotifications = new ArrayList<>(); - destinationRepo - // Retrieve all destinations - .findAll() - .stream() - // Check if notification should be sent for this destinations - .filter(this::checkDestinationLastVerification) - .forEach( - destinationEntity -> { - // Keep previous check date - LocalDateTime previousCheck = destinationEntity.getEmailLastCheck(); - // Update destination last check date - destinationEntity.setEmailLastCheck(LocalDateTime.now(ZoneId.of("CET"))); - destinationRepo.save(destinationEntity); - // Retrieve all TransferStatusEntities for this destination after the last email check - List transferStatusEntitiesDestinationsLastCheck = - retrieveTransferStatusDestinationLastCheck(destinationEntity, previousCheck); - // Gather TransferStatus by Source and Study: >> - Map>> transferStatusBySourceAndStudy = - gatherTransferStatusBySourceAndStudy(transferStatusEntitiesDestinationsLastCheck); - // Build the notifications to send - buildTransferMonitoringNotifications( - transferMonitoringNotifications, transferStatusBySourceAndStudy); - }); - return transferMonitoringNotifications; - } - - /** - * Build transfer notifications to send. - * - * @param transferMonitoringNotifications List of notifications to fill - * @param transferStatusBySourceAndStudy Map of TransferStatus by Source and Study:
- * >> - */ - private void buildTransferMonitoringNotifications( - List transferMonitoringNotifications, - Map>> transferStatusBySourceAndStudy) { - transferStatusBySourceAndStudy.forEach( - // By source - (source, transferStatusByStudy) -> { - transferStatusByStudy.forEach( - // By study - (study, transferStatusEntities) -> { - // Build the transfer notification - TransferMonitoringNotification transferMonitoringNotification = - buildTransferMonitoringNotification(transferStatusEntities); - if (transferMonitoringNotification != null) { - transferMonitoringNotifications.add(transferMonitoringNotification); - } - }); - }); - } - - /** - * Build TransferMonitoringNotification depending on transferStatusEntities in parameter. - * Calculate number of success/errors, determine distinct reasons of not transferring and select - * values to display in the notification (originals or de-identified) depending on the flag - * deidentification in the destination. - * - * @param transferStatusEntities TransferStatusEntity to evaluate - * @return populated TransferMonitoringNotification - */ - private TransferMonitoringNotification buildTransferMonitoringNotification( - List transferStatusEntities) { - TransferMonitoringNotification transferMonitoringNotification = null; - Optional firstTransferStatusOpt = - transferStatusEntities.stream().findFirst(); - - if (firstTransferStatusOpt.isPresent()) { - TransferStatusEntity firstTransferStatus = firstTransferStatusOpt.get(); - transferMonitoringNotification = new TransferMonitoringNotification(); - - // Build the serie notification part - transferMonitoringNotification.setSerieSummaryNotifications( - buildSeriesSummaryNotification( - transferStatusEntities, - firstTransferStatus.getDestinationEntity().isDesidentification())); - - // Has at least one file not transferred - boolean hasAtLeastOneFileNotTransferred = - transferMonitoringNotification.getSerieSummaryNotifications().stream() - .anyMatch(ssm -> ssm.getNbTransferNotSent() > 0); - - // Temporary disable send of notification de-identified and in error - // TODO: have a discussion with business to know how to handle such cases - if (hasAtLeastOneFileNotTransferred - && firstTransferStatus.getDestinationEntity().isDesidentification()) { - return null; - } - - // Check if we should use original or de-identified values - boolean useOriginalValues = - determineUseOfOriginalOrDeIdentifyValues( - hasAtLeastOneFileNotTransferred, - firstTransferStatus.getDestinationEntity().isDesidentification()); - - // Set values in transferMonitoringNotification - buildTransferMonitoringNotificationSetValues( - transferMonitoringNotification, - firstTransferStatus, - hasAtLeastOneFileNotTransferred, - useOriginalValues); - } - return transferMonitoringNotification; - } - - /** - * Set values in transferMonitoringNotification built - * - * @param transferMonitoringNotification TransferMonitoringNotification built - * @param transferStatusEntity Transfer status - * @param hasAtLeastOneFileNotTransferred Has at least one file not transferred - * @param useOriginalValues Flag to know if we should use original values - */ - private void buildTransferMonitoringNotificationSetValues( - TransferMonitoringNotification transferMonitoringNotification, - TransferStatusEntity transferStatusEntity, - boolean hasAtLeastOneFileNotTransferred, - boolean useOriginalValues) { - transferMonitoringNotification.setFrom( - SystemPropertyUtil.retrieveSystemProperty( - "MAIL_SMTP_SENDER", Notification.MAIL_SMTP_SENDER)); - transferMonitoringNotification.setTo(transferStatusEntity.getDestinationEntity().getNotify()); - transferMonitoringNotification.setPatientId( - useOriginalValues - ? transferStatusEntity.getPatientIdOriginal() - : transferStatusEntity.getPatientIdToSend()); - transferMonitoringNotification.setStudyUid( - useOriginalValues - ? transferStatusEntity.getStudyUidOriginal() - : transferStatusEntity.getStudyUidToSend()); - transferMonitoringNotification.setAccessionNumber( - useOriginalValues - ? transferStatusEntity.getAccessionNumberOriginal() - : transferStatusEntity.getAccessionNumberToSend()); - transferMonitoringNotification.setStudyDescription( - useOriginalValues - ? transferStatusEntity.getStudyDescriptionOriginal() - : transferStatusEntity.getStudyDescriptionToSend()); - transferMonitoringNotification.setStudyDate( - useOriginalValues - ? transferStatusEntity.getStudyDateOriginal() - : transferStatusEntity.getStudyDateToSend()); - transferMonitoringNotification.setSource( - transferStatusEntity.getForwardNodeEntity().getFwdAeTitle()); - transferMonitoringNotification.setDestination( - Objects.equals( - transferStatusEntity.getDestinationEntity().getDestinationType(), - DestinationType.dicom) - ? transferStatusEntity.getDestinationEntity().toStringDicomNotificationDestination() - : transferStatusEntity.getDestinationEntity().getUrl()); - transferMonitoringNotification.setSubject( - buildSubject(hasAtLeastOneFileNotTransferred, useOriginalValues, transferStatusEntity)); - } - - /** - * Build notification subject email - * - * @param hasAtLeastOneFileNotTransferred Flag to know if there is at least one file not - * transferred - * @param useOriginalValues Check if we should use original or de-identified values - * @param transferStatusEntity TransferStatusEntity to evaluate - * @return Subject built - */ - private String buildSubject( - boolean hasAtLeastOneFileNotTransferred, - boolean useOriginalValues, - TransferStatusEntity transferStatusEntity) { - StringBuilder subject = new StringBuilder(); - if (hasAtLeastOneFileNotTransferred) { - subject.append(transferStatusEntity.getDestinationEntity().getNotifyObjectErrorPrefix()); - subject.append(Notification.SPACE); - } - subject.append( - String.format( - transferStatusEntity.getDestinationEntity().getNotifyObjectPattern(), - buildSubjectValues(useOriginalValues, transferStatusEntity))); - return subject.toString(); - } - - /** - * Build list of values to add to the subject - * - * @param useOriginalValues Flag to know if we should use original or de-identified values - * @param transferStatusEntity TransferStatusEntity to evaluate - * @return List of values to add to the subject - */ - private Object[] buildSubjectValues( - boolean useOriginalValues, TransferStatusEntity transferStatusEntity) { - List subjectValues = new ArrayList<>(); - - // Determine the values to add to the subject depending on the params set in the destination - String[] notifyObjectValues = - (transferStatusEntity.getDestinationEntity().getNotifyObjectValues() == null - ? Notification.DEFAULT_SUBJECT_VALUES - : transferStatusEntity.getDestinationEntity().getNotifyObjectValues()) - .split(Notification.COMMA_SEPARATOR); - - // Select the values to add - for (String notifyObjectValue : notifyObjectValues) { - if (Objects.equals(Notification.PARAM_PATIENT_ID, notifyObjectValue)) { - // Patient ID - subjectValues.add( - buildSubjectValue( - useOriginalValues, - transferStatusEntity.getPatientIdOriginal(), - transferStatusEntity.getPatientIdToSend())); - } else if (Objects.equals(Notification.PARAM_STUDY_DESCRIPTION, notifyObjectValue)) { - // Study description - subjectValues.add( - buildSubjectValue( - useOriginalValues, - transferStatusEntity.getStudyDescriptionOriginal(), - transferStatusEntity.getStudyDescriptionToSend())); - } else if (Objects.equals(Notification.PARAM_STUDY_INSTANCE_UID, notifyObjectValue)) { - // Study uid - subjectValues.add( - buildSubjectValue( - useOriginalValues, - transferStatusEntity.getStudyUidOriginal(), - transferStatusEntity.getStudyUidToSend())); - } else if (Objects.equals(Notification.PARAM_STUDY_DATE, notifyObjectValue)) { - // Study date - subjectValues.add( - useOriginalValues - ? transferStatusEntity.getStudyDateOriginal() == null - ? Notification.EMPTY_STRING - : transferStatusEntity.getStudyDateOriginal().toString() - : transferStatusEntity.getStudyDateToSend() == null - ? Notification.EMPTY_STRING - : transferStatusEntity.getStudyDateToSend().toString()); - } - } - return subjectValues.toArray(); - } - - /** - * Build subject value, if null set empty string in the subject - * - * @param useOriginalValues Flag to know if we should use original value - * @param original Value original - * @param toSend Value transformed to send - * @return subject value - */ - private String buildSubjectValue(boolean useOriginalValues, String original, String toSend) { - return useOriginalValues - ? original == null ? Notification.EMPTY_STRING : original - : toSend == null ? Notification.EMPTY_STRING : toSend; - } - - /** - * Build transfer serie summary results - * - * @param transferStatusEntities TransferStatus to evaluate - * @param isDestinationDeIdentify Flag to know if the destination should be de-identify - * @return Serie summary notifications - */ - private List buildSeriesSummaryNotification( - List transferStatusEntities, boolean isDestinationDeIdentify) { - List serieSummaryNotifications = new ArrayList<>(); - // Group by serie uid - Map> transferStatusEntitiesBySerieUid = - transferStatusEntities.stream() - .collect(Collectors.groupingBy(TransferStatusEntity::getSerieUidOriginal)); - transferStatusEntitiesBySerieUid.forEach( - (serieUidOriginal, transfersToEvaluate) -> { - Optional firstTransferStatusEntityOpt = - transfersToEvaluate.stream().findFirst(); - if (firstTransferStatusEntityOpt.isPresent()) { - TransferStatusEntity firstTransferStatusEntity = firstTransferStatusEntityOpt.get(); - // Build serie summary - serieSummaryNotifications.add( - buildSerieSummaryNotification( - isDestinationDeIdentify, transfersToEvaluate, firstTransferStatusEntity)); - } - }); - - return serieSummaryNotifications; - } - - /** - * Build summary notification for the serie in parameter - * - * @param isDestinationDeIdentify Flag to know if the destination should be de-identify - * @param transfersToEvaluate Transfers to evaluate - * @param transferStatusEntity TransferStatus containing general series values to set - * @return Summary notification for this serie - */ - private SerieSummaryNotification buildSerieSummaryNotification( - boolean isDestinationDeIdentify, - List transfersToEvaluate, - TransferStatusEntity transferStatusEntity) { - SerieSummaryNotification serieSummaryNotification = new SerieSummaryNotification(); - // Number transfers sent - serieSummaryNotification.setNbTransferSent( - transfersToEvaluate.stream().filter(TransferStatusEntity::isSent).count()); - // Number transfers not sent - serieSummaryNotification.setNbTransferNotSent( - transfersToEvaluate.stream().filter(t -> !t.isSent()).count()); - // Distinct reasons - serieSummaryNotification.setUnTransferedReasons( - determineUnTransferredReasons(transfersToEvaluate)); - // Flag to know if we should use original or de-identify values - boolean useOriginalValues = - determineUseOfOriginalOrDeIdentifyValues( - serieSummaryNotification.getNbTransferNotSent() > 0, isDestinationDeIdentify); - serieSummaryNotification.setSerieUid( - useOriginalValues - ? transferStatusEntity.getSerieUidOriginal() - : transferStatusEntity.getSerieUidToSend()); - serieSummaryNotification.setSerieDescription( - useOriginalValues - ? transferStatusEntity.getSerieDescriptionOriginal() - : transferStatusEntity.getSerieDescriptionToSend()); - serieSummaryNotification.setSerieDate( - useOriginalValues - ? transferStatusEntity.getSerieDateOriginal() - : transferStatusEntity.getSerieDateToSend()); - return serieSummaryNotification; - } - - /** - * Determine distinct reasons of not transferring - * - * @param transfersToEvaluate Transfers to evaluate - * @return Distinct reasons found - */ - private List determineUnTransferredReasons( - List transfersToEvaluate) { - return transfersToEvaluate.stream() - .map(TransferStatusEntity::getReason) - .filter(Objects::nonNull) - .distinct() - .collect(Collectors.toList()); - } - - /** - * Determine if we have to use originals or de-identify values. If any transfer not sent or flag - * deidentification for the destination is false: use originals values - * - * @param hasTransferNotSent Flag to know if there are transfer not sent - * @param isDestinationDeIdentify Is deidentification requested for the destination - * @return true if we have to use originals values, false otherwise - */ - private boolean determineUseOfOriginalOrDeIdentifyValues( - boolean hasTransferNotSent, boolean isDestinationDeIdentify) { - return hasTransferNotSent || !isDestinationDeIdentify; - } - - /** - * Gather TransferStatusEntities by Source and Study - * - * @param transferStatusEntities Entities to gather - * @return Map of >> - */ - private Map>> gatherTransferStatusBySourceAndStudy( - List transferStatusEntities) { - return transferStatusEntities.stream() - .collect( - Collectors.groupingBy( - TransferStatusEntity::getForwardNodeId, - Collectors.groupingBy(TransferStatusEntity::getStudyUidOriginal))); - } - - /** - * Retrieve TransferStatusEntities for this destination after the last email check - * - * @param destinationEntity Destination to look for - * @param lastCheck Last check for this destination - * @return TransferStatusEntity found - */ - private List retrieveTransferStatusDestinationLastCheck( - DestinationEntity destinationEntity, LocalDateTime lastCheck) { - return lastCheck == null - ? transferStatusRepo.findByDestinationId(destinationEntity.getId()) - : transferStatusRepo.findByDestinationIdAndTransferDateAfter( - destinationEntity.getId(), lastCheck); - } - - /** - * Check if notification should be sent depending on last check of notification (compare to - * notification interval of the destination and current date)
- * A transfer should not be in progress to send the notification and an extra timer of 10s is - * added for serie transfers which are not immediately sent each time (a delay is occurring - * between transfer of files in the same serie) - * - * @param destinationEntity Destination to evaluate - * @return true if the notification can be process, false otherwise - */ - private boolean checkDestinationLastVerification(DestinationEntity destinationEntity) { - return !destinationEntity.isTransferInProgress() - && destinationEntity.getLastTransfer() != null - // Add extra timer delay in order to insure transfer of serie is over - && destinationEntity - .getLastTransfer() - .plusSeconds(Notification.EXTRA_TIMER_DELAY) - .isBefore(LocalDateTime.now(ZoneId.of("CET"))) - && (destinationEntity.getEmailLastCheck() == null - || destinationEntity - .getEmailLastCheck() - .plusSeconds(destinationEntity.getNotifyInterval().longValue()) - .isBefore(LocalDateTime.now(ZoneId.of("CET")))) - && destinationEntity.isActivateNotification(); - } - - /** - * Prepare and send the notification with values in parameter - * - * @param transferMonitoringNotification Values to add to the thymeleaf template - */ - private void prepareAndSendNotification( - TransferMonitoringNotification transferMonitoringNotification) { - Context context = new Context(); - context.setVariable(Notification.CONTEXT_THYMELEAF, transferMonitoringNotification); - MimeMessage mimeMessage = javaMailSender.createMimeMessage(); - MimeMessageHelper helper = new MimeMessageHelper(mimeMessage); - try { - helper.setSubject(transferMonitoringNotification.getSubject()); - helper.setText(templateEngine.process(Notification.TEMPLATE_THYMELEAF, context), true); - helper.setTo(InternetAddress.parse(transferMonitoringNotification.getTo())); - helper.setFrom(transferMonitoringNotification.getFrom()); - } catch (MessagingException e) { - LOGGER.error("Notification error when preparing email to send: {}", e.getMessage()); - } - javaMailSender.send(mimeMessage); - } + private static final Logger LOGGER = LoggerFactory.getLogger(NotificationService.class); + + // Services + private final TemplateEngine templateEngine; + + private final JavaMailSender javaMailSender; + + // Repositories + private final TransferStatusRepo transferStatusRepo; + + private final DestinationRepo destinationRepo; + + @Autowired + public NotificationService(final TemplateEngine templateEngine, final JavaMailSender javaMailSender, + final TransferStatusRepo transferStatusRepo, final DestinationRepo destinationRepo) { + this.templateEngine = templateEngine; + this.javaMailSender = javaMailSender; + this.transferStatusRepo = transferStatusRepo; + this.destinationRepo = destinationRepo; + } + + /** + * In a regular period of time, check for new inputs in the transfer notifications, + * build the notifications and send them via email. + */ + @Scheduled(fixedRate = 10 * 1000) + private void determineNotificationToSend() { + buildNotificationsToSend().forEach(this::prepareAndSendNotification); + } + + /** + * Build transfer notification to send + * @return notifications to send + */ + List buildNotificationsToSend() { + List transferMonitoringNotifications = new ArrayList<>(); + destinationRepo + // Retrieve all destinations + .findAll().stream() + // Check if notification should be sent for this destinations + .filter(this::checkDestinationLastVerification).forEach(destinationEntity -> { + // Keep previous check date + LocalDateTime previousCheck = destinationEntity.getEmailLastCheck(); + // Update destination last check date + destinationEntity.setEmailLastCheck(LocalDateTime.now(ZoneId.of("CET"))); + destinationRepo.save(destinationEntity); + // Retrieve all TransferStatusEntities for this destination after the + // last email check + List transferStatusEntitiesDestinationsLastCheck = retrieveTransferStatusDestinationLastCheck( + destinationEntity, previousCheck); + // Gather TransferStatus by Source and Study: >> + Map>> transferStatusBySourceAndStudy = gatherTransferStatusBySourceAndStudy( + transferStatusEntitiesDestinationsLastCheck); + // Build the notifications to send + buildTransferMonitoringNotifications(transferMonitoringNotifications, + transferStatusBySourceAndStudy); + }); + return transferMonitoringNotifications; + } + + /** + * Build transfer notifications to send. + * @param transferMonitoringNotifications List of notifications to fill + * @param transferStatusBySourceAndStudy Map of TransferStatus by Source and Study: + *
+ * >> + */ + private void buildTransferMonitoringNotifications( + List transferMonitoringNotifications, + Map>> transferStatusBySourceAndStudy) { + transferStatusBySourceAndStudy.forEach( + // By source + (source, transferStatusByStudy) -> { + transferStatusByStudy.forEach( + // By study + (study, transferStatusEntities) -> { + // Build the transfer notification + TransferMonitoringNotification transferMonitoringNotification = buildTransferMonitoringNotification( + transferStatusEntities); + if (transferMonitoringNotification != null) { + transferMonitoringNotifications.add(transferMonitoringNotification); + } + }); + }); + } + + /** + * Build TransferMonitoringNotification depending on transferStatusEntities in + * parameter. Calculate number of success/errors, determine distinct reasons of not + * transferring and select values to display in the notification (originals or + * de-identified) depending on the flag deidentification in the destination. + * @param transferStatusEntities TransferStatusEntity to evaluate + * @return populated TransferMonitoringNotification + */ + private TransferMonitoringNotification buildTransferMonitoringNotification( + List transferStatusEntities) { + TransferMonitoringNotification transferMonitoringNotification = null; + Optional firstTransferStatusOpt = transferStatusEntities.stream().findFirst(); + + if (firstTransferStatusOpt.isPresent()) { + TransferStatusEntity firstTransferStatus = firstTransferStatusOpt.get(); + transferMonitoringNotification = new TransferMonitoringNotification(); + + // Build the serie notification part + transferMonitoringNotification.setSerieSummaryNotifications(buildSeriesSummaryNotification( + transferStatusEntities, firstTransferStatus.getDestinationEntity().isDesidentification())); + + // Has at least one file not transferred + boolean hasAtLeastOneFileNotTransferred = transferMonitoringNotification.getSerieSummaryNotifications() + .stream().anyMatch(ssm -> ssm.getNbTransferNotSent() > 0); + + // Temporary disable send of notification de-identified and in error + // TODO: have a discussion with business to know how to handle such cases + if (hasAtLeastOneFileNotTransferred && firstTransferStatus.getDestinationEntity().isDesidentification()) { + return null; + } + + // Check if we should use original or de-identified values + boolean useOriginalValues = determineUseOfOriginalOrDeIdentifyValues(hasAtLeastOneFileNotTransferred, + firstTransferStatus.getDestinationEntity().isDesidentification()); + + // Set values in transferMonitoringNotification + buildTransferMonitoringNotificationSetValues(transferMonitoringNotification, firstTransferStatus, + hasAtLeastOneFileNotTransferred, useOriginalValues); + } + return transferMonitoringNotification; + } + + /** + * Set values in transferMonitoringNotification built + * @param transferMonitoringNotification TransferMonitoringNotification built + * @param transferStatusEntity Transfer status + * @param hasAtLeastOneFileNotTransferred Has at least one file not transferred + * @param useOriginalValues Flag to know if we should use original values + */ + private void buildTransferMonitoringNotificationSetValues( + TransferMonitoringNotification transferMonitoringNotification, TransferStatusEntity transferStatusEntity, + boolean hasAtLeastOneFileNotTransferred, boolean useOriginalValues) { + transferMonitoringNotification + .setFrom(SystemPropertyUtil.retrieveSystemProperty("MAIL_SMTP_SENDER", Notification.MAIL_SMTP_SENDER)); + transferMonitoringNotification.setTo(transferStatusEntity.getDestinationEntity().getNotify()); + transferMonitoringNotification.setPatientId(useOriginalValues ? transferStatusEntity.getPatientIdOriginal() + : transferStatusEntity.getPatientIdToSend()); + transferMonitoringNotification.setStudyUid(useOriginalValues ? transferStatusEntity.getStudyUidOriginal() + : transferStatusEntity.getStudyUidToSend()); + transferMonitoringNotification.setAccessionNumber(useOriginalValues + ? transferStatusEntity.getAccessionNumberOriginal() : transferStatusEntity.getAccessionNumberToSend()); + transferMonitoringNotification + .setStudyDescription(useOriginalValues ? transferStatusEntity.getStudyDescriptionOriginal() + : transferStatusEntity.getStudyDescriptionToSend()); + transferMonitoringNotification.setStudyDate(useOriginalValues ? transferStatusEntity.getStudyDateOriginal() + : transferStatusEntity.getStudyDateToSend()); + transferMonitoringNotification.setSource(transferStatusEntity.getForwardNodeEntity().getFwdAeTitle()); + transferMonitoringNotification.setDestination( + Objects.equals(transferStatusEntity.getDestinationEntity().getDestinationType(), DestinationType.dicom) + ? transferStatusEntity.getDestinationEntity().toStringDicomNotificationDestination() + : transferStatusEntity.getDestinationEntity().getUrl()); + transferMonitoringNotification + .setSubject(buildSubject(hasAtLeastOneFileNotTransferred, useOriginalValues, transferStatusEntity)); + } + + /** + * Build notification subject email + * @param hasAtLeastOneFileNotTransferred Flag to know if there is at least one file + * not transferred + * @param useOriginalValues Check if we should use original or de-identified values + * @param transferStatusEntity TransferStatusEntity to evaluate + * @return Subject built + */ + private String buildSubject(boolean hasAtLeastOneFileNotTransferred, boolean useOriginalValues, + TransferStatusEntity transferStatusEntity) { + StringBuilder subject = new StringBuilder(); + if (hasAtLeastOneFileNotTransferred) { + subject.append(transferStatusEntity.getDestinationEntity().getNotifyObjectErrorPrefix()); + subject.append(Notification.SPACE); + } + subject.append(String.format(transferStatusEntity.getDestinationEntity().getNotifyObjectPattern(), + buildSubjectValues(useOriginalValues, transferStatusEntity))); + return subject.toString(); + } + + /** + * Build list of values to add to the subject + * @param useOriginalValues Flag to know if we should use original or de-identified + * values + * @param transferStatusEntity TransferStatusEntity to evaluate + * @return List of values to add to the subject + */ + private Object[] buildSubjectValues(boolean useOriginalValues, TransferStatusEntity transferStatusEntity) { + List subjectValues = new ArrayList<>(); + + // Determine the values to add to the subject depending on the params set in the + // destination + String[] notifyObjectValues = (transferStatusEntity.getDestinationEntity().getNotifyObjectValues() == null + ? Notification.DEFAULT_SUBJECT_VALUES + : transferStatusEntity.getDestinationEntity().getNotifyObjectValues()) + .split(Notification.COMMA_SEPARATOR); + + // Select the values to add + for (String notifyObjectValue : notifyObjectValues) { + if (Objects.equals(Notification.PARAM_PATIENT_ID, notifyObjectValue)) { + // Patient ID + subjectValues.add(buildSubjectValue(useOriginalValues, transferStatusEntity.getPatientIdOriginal(), + transferStatusEntity.getPatientIdToSend())); + } + else if (Objects.equals(Notification.PARAM_STUDY_DESCRIPTION, notifyObjectValue)) { + // Study description + subjectValues + .add(buildSubjectValue(useOriginalValues, transferStatusEntity.getStudyDescriptionOriginal(), + transferStatusEntity.getStudyDescriptionToSend())); + } + else if (Objects.equals(Notification.PARAM_STUDY_INSTANCE_UID, notifyObjectValue)) { + // Study uid + subjectValues.add(buildSubjectValue(useOriginalValues, transferStatusEntity.getStudyUidOriginal(), + transferStatusEntity.getStudyUidToSend())); + } + else if (Objects.equals(Notification.PARAM_STUDY_DATE, notifyObjectValue)) { + // Study date + subjectValues.add(useOriginalValues + ? transferStatusEntity.getStudyDateOriginal() == null ? Notification.EMPTY_STRING + : transferStatusEntity.getStudyDateOriginal().toString() + : transferStatusEntity.getStudyDateToSend() == null ? Notification.EMPTY_STRING + : transferStatusEntity.getStudyDateToSend().toString()); + } + } + return subjectValues.toArray(); + } + + /** + * Build subject value, if null set empty string in the subject + * @param useOriginalValues Flag to know if we should use original value + * @param original Value original + * @param toSend Value transformed to send + * @return subject value + */ + private String buildSubjectValue(boolean useOriginalValues, String original, String toSend) { + return useOriginalValues ? original == null ? Notification.EMPTY_STRING : original + : toSend == null ? Notification.EMPTY_STRING : toSend; + } + + /** + * Build transfer serie summary results + * @param transferStatusEntities TransferStatus to evaluate + * @param isDestinationDeIdentify Flag to know if the destination should be + * de-identify + * @return Serie summary notifications + */ + private List buildSeriesSummaryNotification( + List transferStatusEntities, boolean isDestinationDeIdentify) { + List serieSummaryNotifications = new ArrayList<>(); + // Group by serie uid + Map> transferStatusEntitiesBySerieUid = transferStatusEntities.stream() + .collect(Collectors.groupingBy(TransferStatusEntity::getSerieUidOriginal)); + transferStatusEntitiesBySerieUid.forEach((serieUidOriginal, transfersToEvaluate) -> { + Optional firstTransferStatusEntityOpt = transfersToEvaluate.stream().findFirst(); + if (firstTransferStatusEntityOpt.isPresent()) { + TransferStatusEntity firstTransferStatusEntity = firstTransferStatusEntityOpt.get(); + // Build serie summary + serieSummaryNotifications.add(buildSerieSummaryNotification(isDestinationDeIdentify, + transfersToEvaluate, firstTransferStatusEntity)); + } + }); + + return serieSummaryNotifications; + } + + /** + * Build summary notification for the serie in parameter + * @param isDestinationDeIdentify Flag to know if the destination should be + * de-identify + * @param transfersToEvaluate Transfers to evaluate + * @param transferStatusEntity TransferStatus containing general series values to set + * @return Summary notification for this serie + */ + private SerieSummaryNotification buildSerieSummaryNotification(boolean isDestinationDeIdentify, + List transfersToEvaluate, TransferStatusEntity transferStatusEntity) { + SerieSummaryNotification serieSummaryNotification = new SerieSummaryNotification(); + // Number transfers sent + serieSummaryNotification + .setNbTransferSent(transfersToEvaluate.stream().filter(TransferStatusEntity::isSent).count()); + // Number transfers not sent + serieSummaryNotification.setNbTransferNotSent(transfersToEvaluate.stream().filter(t -> !t.isSent()).count()); + // Distinct reasons + serieSummaryNotification.setUnTransferedReasons(determineUnTransferredReasons(transfersToEvaluate)); + // Flag to know if we should use original or de-identify values + boolean useOriginalValues = determineUseOfOriginalOrDeIdentifyValues( + serieSummaryNotification.getNbTransferNotSent() > 0, isDestinationDeIdentify); + serieSummaryNotification.setSerieUid(useOriginalValues ? transferStatusEntity.getSerieUidOriginal() + : transferStatusEntity.getSerieUidToSend()); + serieSummaryNotification + .setSerieDescription(useOriginalValues ? transferStatusEntity.getSerieDescriptionOriginal() + : transferStatusEntity.getSerieDescriptionToSend()); + serieSummaryNotification.setSerieDate(useOriginalValues ? transferStatusEntity.getSerieDateOriginal() + : transferStatusEntity.getSerieDateToSend()); + return serieSummaryNotification; + } + + /** + * Determine distinct reasons of not transferring + * @param transfersToEvaluate Transfers to evaluate + * @return Distinct reasons found + */ + private List determineUnTransferredReasons(List transfersToEvaluate) { + return transfersToEvaluate.stream().map(TransferStatusEntity::getReason).filter(Objects::nonNull).distinct() + .collect(Collectors.toList()); + } + + /** + * Determine if we have to use originals or de-identify values. If any transfer not + * sent or flag deidentification for the destination is false: use originals values + * @param hasTransferNotSent Flag to know if there are transfer not sent + * @param isDestinationDeIdentify Is deidentification requested for the destination + * @return true if we have to use originals values, false otherwise + */ + private boolean determineUseOfOriginalOrDeIdentifyValues(boolean hasTransferNotSent, + boolean isDestinationDeIdentify) { + return hasTransferNotSent || !isDestinationDeIdentify; + } + + /** + * Gather TransferStatusEntities by Source and Study + * @param transferStatusEntities Entities to gather + * @return Map of >> + */ + private Map>> gatherTransferStatusBySourceAndStudy( + List transferStatusEntities) { + return transferStatusEntities.stream().collect(Collectors.groupingBy(TransferStatusEntity::getForwardNodeId, + Collectors.groupingBy(TransferStatusEntity::getStudyUidOriginal))); + } + + /** + * Retrieve TransferStatusEntities for this destination after the last email check + * @param destinationEntity Destination to look for + * @param lastCheck Last check for this destination + * @return TransferStatusEntity found + */ + private List retrieveTransferStatusDestinationLastCheck(DestinationEntity destinationEntity, + LocalDateTime lastCheck) { + return lastCheck == null ? transferStatusRepo.findByDestinationId(destinationEntity.getId()) + : transferStatusRepo.findByDestinationIdAndTransferDateAfter(destinationEntity.getId(), lastCheck); + } + + /** + * Check if notification should be sent depending on last check of notification + * (compare to notification interval of the destination and current date)
+ * A transfer should not be in progress to send the notification and an extra timer of + * 10s is added for serie transfers which are not immediately sent each time (a delay + * is occurring between transfer of files in the same serie) + * @param destinationEntity Destination to evaluate + * @return true if the notification can be process, false otherwise + */ + private boolean checkDestinationLastVerification(DestinationEntity destinationEntity) { + return !destinationEntity.isTransferInProgress() && destinationEntity.getLastTransfer() != null + // Add extra timer delay in order to insure transfer of serie is over + && destinationEntity.getLastTransfer().plusSeconds(Notification.EXTRA_TIMER_DELAY) + .isBefore(LocalDateTime.now(ZoneId.of("CET"))) + && (destinationEntity.getEmailLastCheck() == null || destinationEntity.getEmailLastCheck() + .plusSeconds(destinationEntity.getNotifyInterval().longValue()) + .isBefore(LocalDateTime.now(ZoneId.of("CET")))) + && destinationEntity.isActivateNotification(); + } + + /** + * Prepare and send the notification with values in parameter + * @param transferMonitoringNotification Values to add to the thymeleaf template + */ + private void prepareAndSendNotification(TransferMonitoringNotification transferMonitoringNotification) { + Context context = new Context(); + context.setVariable(Notification.CONTEXT_THYMELEAF, transferMonitoringNotification); + MimeMessage mimeMessage = javaMailSender.createMimeMessage(); + MimeMessageHelper helper = new MimeMessageHelper(mimeMessage); + try { + helper.setSubject(transferMonitoringNotification.getSubject()); + helper.setText(templateEngine.process(Notification.TEMPLATE_THYMELEAF, context), true); + helper.setTo(InternetAddress.parse(transferMonitoringNotification.getTo())); + helper.setFrom(transferMonitoringNotification.getFrom()); + } + catch (MessagingException e) { + LOGGER.error("Notification error when preparing email to send: {}", e.getMessage()); + } + javaMailSender.send(mimeMessage); + } + } diff --git a/src/main/java/org/karnak/backend/service/ProjectService.java b/src/main/java/org/karnak/backend/service/ProjectService.java index 01c15839d..947470070 100644 --- a/src/main/java/org/karnak/backend/service/ProjectService.java +++ b/src/main/java/org/karnak/backend/service/ProjectService.java @@ -24,91 +24,83 @@ @Service public class ProjectService { - // Repositories - private final ProjectRepo projectRepo; + // Repositories + private final ProjectRepo projectRepo; - // Event publisher - private final ApplicationEventPublisher applicationEventPublisher; + // Event publisher + private final ApplicationEventPublisher applicationEventPublisher; - /** - * Autowired constructor - * - * @param projectRepo Project repository - * @param applicationEventPublisher Application Event Publisher - */ - @Autowired - public ProjectService( - final ProjectRepo projectRepo, final ApplicationEventPublisher applicationEventPublisher) { - this.projectRepo = projectRepo; - this.applicationEventPublisher = applicationEventPublisher; - } + /** + * Autowired constructor + * @param projectRepo Project repository + * @param applicationEventPublisher Application Event Publisher + */ + @Autowired + public ProjectService(final ProjectRepo projectRepo, final ApplicationEventPublisher applicationEventPublisher) { + this.projectRepo = projectRepo; + this.applicationEventPublisher = applicationEventPublisher; + } - /** - * Save in DB the project in parameter - * - * @param projectEntity Project to save - */ - public ProjectEntity save(ProjectEntity projectEntity) { - return projectRepo.saveAndFlush(projectEntity); - } + /** + * Save in DB the project in parameter + * @param projectEntity Project to save + */ + public ProjectEntity save(ProjectEntity projectEntity) { + return projectRepo.saveAndFlush(projectEntity); + } - /** - * Update project and destinations - * - * @param projectEntity Project to updated - */ - public void update(ProjectEntity projectEntity) { - if (projectEntity.getId() != null) { - projectRepo.saveAndFlush(projectEntity); - updateDestinations(projectEntity); - } - } + /** + * Update project and destinations + * @param projectEntity Project to updated + */ + public void update(ProjectEntity projectEntity) { + if (projectEntity.getId() != null) { + projectRepo.saveAndFlush(projectEntity); + updateDestinations(projectEntity); + } + } - /** - * Update destinations - * - * @param projectEntity Project destinations to update - */ - private void updateDestinations(ProjectEntity projectEntity) { - for (DestinationEntity destinationEntity : projectEntity.getDestinationEntities()) { - applicationEventPublisher.publishEvent( - new NodeEvent(destinationEntity, NodeEventType.UPDATE)); - } - } + /** + * Update destinations + * @param projectEntity Project destinations to update + */ + private void updateDestinations(ProjectEntity projectEntity) { + for (DestinationEntity destinationEntity : projectEntity.getDestinationEntities()) { + applicationEventPublisher.publishEvent(new NodeEvent(destinationEntity, NodeEventType.UPDATE)); + } + } - /** - * Remove project - * - * @param projectEntity Project to remove - */ - public void remove(ProjectEntity projectEntity) { - projectRepo.deleteById(projectEntity.getId()); - projectRepo.flush(); - } + /** + * Remove project + * @param projectEntity Project to remove + */ + public void remove(ProjectEntity projectEntity) { + projectRepo.deleteById(projectEntity.getId()); + projectRepo.flush(); + } - /** - * Retrieve all projects - * - * @return projects found - */ - public List getAllProjects() { - return projectRepo.findAll(); - } + /** + * Retrieve all projects + * @return projects found + */ + public List getAllProjects() { + return projectRepo.findAll(); + } + + /** + * Retrieve project by id + * @param id Id to look for + * @return project found + */ + public ProjectEntity retrieveProject(Long id) { + ProjectEntity projectEntity = null; + if (id != null) { + Optional projectEntityOptional = projectRepo.findById(id); + if (projectEntityOptional.isPresent()) { + projectEntity = projectEntityOptional.get(); + } + } + return projectEntity; + } - /** - * Retrieve project by id - * - * @param id Id to look for - * @return project found - */ - public ProjectEntity retrieveProject(Long id) { - ProjectEntity projectEntity = null; - if (id != null) { - Optional projectEntityOptional = projectRepo.findById(id); - if (projectEntityOptional.isPresent()) { - projectEntity = projectEntityOptional.get(); - } - } - return projectEntity; - } } diff --git a/src/main/java/org/karnak/backend/service/PseudonymMappingService.java b/src/main/java/org/karnak/backend/service/PseudonymMappingService.java index f5ebdc682..d1fdff0df 100644 --- a/src/main/java/org/karnak/backend/service/PseudonymMappingService.java +++ b/src/main/java/org/karnak/backend/service/PseudonymMappingService.java @@ -21,44 +21,37 @@ @Service public class PseudonymMappingService { - private static final Logger LOGGER = LoggerFactory.getLogger(PseudonymMappingService.class); + private static final Logger LOGGER = LoggerFactory.getLogger(PseudonymMappingService.class); + + public MainzellistePatient retrieveMainzellistePatient(final String pseudonym) { + MainzellistePatient mainzellistePatient = null; + + // Pseudonym api + PseudonymApi pseudonymApi = new PseudonymApi(); + + // Search pid pseudonym + JSONArray patientFoundJSONArray = pseudonymApi.searchPatient(pseudonym, "pid"); + + // Not found: Search extid pseudonym + if (patientFoundJSONArray == null) { + patientFoundJSONArray = pseudonymApi.searchPatient(pseudonym, "extid"); + } + + // Patient found + if (patientFoundJSONArray != null && !patientFoundJSONArray.isEmpty() && !patientFoundJSONArray.isNull(0)) { + // Retrieve patient from response + JSONObject jsonObject = ((JSONObject) patientFoundJSONArray.getJSONObject(0).get("fields")); + + // Map to model + if (jsonObject != null) { + mainzellistePatient = new MainzellistePatient(pseudonym, jsonObject.getString("patientID"), null, null, + DateTimeUtils.parseDA(jsonObject.getString("patientBirthDate")), + jsonObject.getString("patientSex"), jsonObject.getString("issuerOfPatientID")); + // Set patient name (first/last) + mainzellistePatient.updatePatientName(jsonObject.getString("patientName")); + } + } + return mainzellistePatient; + } - public MainzellistePatient retrieveMainzellistePatient(final String pseudonym) { - MainzellistePatient mainzellistePatient = null; - - // Pseudonym api - PseudonymApi pseudonymApi = new PseudonymApi(); - - // Search pid pseudonym - JSONArray patientFoundJSONArray = pseudonymApi.searchPatient(pseudonym, "pid"); - - // Not found: Search extid pseudonym - if (patientFoundJSONArray == null) { - patientFoundJSONArray = pseudonymApi.searchPatient(pseudonym, "extid"); - } - - // Patient found - if (patientFoundJSONArray != null - && !patientFoundJSONArray.isEmpty() - && !patientFoundJSONArray.isNull(0)) { - // Retrieve patient from response - JSONObject jsonObject = ((JSONObject) patientFoundJSONArray.getJSONObject(0).get("fields")); - - // Map to model - if (jsonObject != null) { - mainzellistePatient = - new MainzellistePatient( - pseudonym, - jsonObject.getString("patientID"), - null, - null, - DateTimeUtils.parseDA(jsonObject.getString("patientBirthDate")), - jsonObject.getString("patientSex"), - jsonObject.getString("issuerOfPatientID")); - // Set patient name (first/last) - mainzellistePatient.updatePatientName(jsonObject.getString("patientName")); - } - } - return mainzellistePatient; - } } diff --git a/src/main/java/org/karnak/backend/service/SOPClassUIDService.java b/src/main/java/org/karnak/backend/service/SOPClassUIDService.java index 9b84c0d09..3dffd7378 100644 --- a/src/main/java/org/karnak/backend/service/SOPClassUIDService.java +++ b/src/main/java/org/karnak/backend/service/SOPClassUIDService.java @@ -22,42 +22,40 @@ @Service public class SOPClassUIDService extends ListDataProvider { - // Repositories - private final SOPClassUIDRepo sopClassUIDRepo; - - @Autowired - public SOPClassUIDService(final SOPClassUIDRepo sopClassUIDRepo) { - super(new ArrayList<>()); - this.sopClassUIDRepo = sopClassUIDRepo; - getItems().addAll(getAllSOPClassUIDs()); - } - - public SOPClassUIDEntity get(Long dataId) { - return sopClassUIDRepo.getSOPClassUIDById(dataId); - } - - public SOPClassUIDEntity getByName(String name) { - return sopClassUIDRepo.getSOPClassUIDByName(name); - } - - public List getAllSOPClassUIDs() { - List list = new ArrayList<>(); - sopClassUIDRepo - .findAll() // - .forEach(list::add); - return list; - } - - public List getAllSOPClassUIDsName() { - return sopClassUIDRepo.findAll().stream() - .map(SOPClassUIDEntity::getName) - .collect(Collectors.toList()); - } - - @Override - public void refreshAll() { - getItems().clear(); - getItems().addAll(getAllSOPClassUIDs()); - super.refreshAll(); - } + // Repositories + private final SOPClassUIDRepo sopClassUIDRepo; + + @Autowired + public SOPClassUIDService(final SOPClassUIDRepo sopClassUIDRepo) { + super(new ArrayList<>()); + this.sopClassUIDRepo = sopClassUIDRepo; + getItems().addAll(getAllSOPClassUIDs()); + } + + public SOPClassUIDEntity get(Long dataId) { + return sopClassUIDRepo.getSOPClassUIDById(dataId); + } + + public SOPClassUIDEntity getByName(String name) { + return sopClassUIDRepo.getSOPClassUIDByName(name); + } + + public List getAllSOPClassUIDs() { + List list = new ArrayList<>(); + sopClassUIDRepo.findAll() // + .forEach(list::add); + return list; + } + + public List getAllSOPClassUIDsName() { + return sopClassUIDRepo.findAll().stream().map(SOPClassUIDEntity::getName).collect(Collectors.toList()); + } + + @Override + public void refreshAll() { + getItems().clear(); + getItems().addAll(getAllSOPClassUIDs()); + super.refreshAll(); + } + } diff --git a/src/main/java/org/karnak/backend/service/SecretService.java b/src/main/java/org/karnak/backend/service/SecretService.java index 5ab808b1c..a45df0f80 100644 --- a/src/main/java/org/karnak/backend/service/SecretService.java +++ b/src/main/java/org/karnak/backend/service/SecretService.java @@ -18,34 +18,33 @@ @Service public class SecretService { - // Repositories - private final SecretRepo secretRepo; + // Repositories + private final SecretRepo secretRepo; - @Autowired - public SecretService(final SecretRepo secretRepo) { - this.secretRepo = secretRepo; - } + @Autowired + public SecretService(final SecretRepo secretRepo) { + this.secretRepo = secretRepo; + } - /** - * Save a secret in db - * - * @param secretEntity Secret to save - * @return Secret saved - */ - public SecretEntity save(SecretEntity secretEntity) { - return secretRepo.saveAndFlush(secretEntity); - } + /** + * Save a secret in db + * @param secretEntity Secret to save + * @return Secret saved + */ + public SecretEntity save(SecretEntity secretEntity) { + return secretRepo.saveAndFlush(secretEntity); + } + + /** + * Save in db a new active secret for the project in parameter + * @param secretEntity Secret to save + * @param projectEntity Project associated to the secret + * @return Secret saved + */ + public SecretEntity saveActiveSecret(SecretEntity secretEntity, ProjectEntity projectEntity) { + secretEntity.setProjectEntity(projectEntity); + secretEntity.setActive(true); + return secretRepo.saveAndFlush(secretEntity); + } - /** - * Save in db a new active secret for the project in parameter - * - * @param secretEntity Secret to save - * @param projectEntity Project associated to the secret - * @return Secret saved - */ - public SecretEntity saveActiveSecret(SecretEntity secretEntity, ProjectEntity projectEntity) { - secretEntity.setProjectEntity(projectEntity); - secretEntity.setActive(true); - return secretRepo.saveAndFlush(secretEntity); - } } diff --git a/src/main/java/org/karnak/backend/service/SourceNodeService.java b/src/main/java/org/karnak/backend/service/SourceNodeService.java index af176c1bb..5de598dff 100644 --- a/src/main/java/org/karnak/backend/service/SourceNodeService.java +++ b/src/main/java/org/karnak/backend/service/SourceNodeService.java @@ -20,56 +20,52 @@ @Service public class SourceNodeService { - // Repositories - private final DicomSourceNodeRepo dicomSourceNodeRepo; + // Repositories + private final DicomSourceNodeRepo dicomSourceNodeRepo; - // Services - private final ForwardNodeService forwardNodeService; + // Services + private final ForwardNodeService forwardNodeService; - // Event publisher - private final ApplicationEventPublisher applicationEventPublisher; + // Event publisher + private final ApplicationEventPublisher applicationEventPublisher; - @Autowired - public SourceNodeService( - final DicomSourceNodeRepo dicomSourceNodeRepo, - final ForwardNodeService forwardNodeService, - final ApplicationEventPublisher applicationEventPublisher) { - this.dicomSourceNodeRepo = dicomSourceNodeRepo; - this.forwardNodeService = forwardNodeService; - this.applicationEventPublisher = applicationEventPublisher; - } + @Autowired + public SourceNodeService(final DicomSourceNodeRepo dicomSourceNodeRepo, final ForwardNodeService forwardNodeService, + final ApplicationEventPublisher applicationEventPublisher) { + this.dicomSourceNodeRepo = dicomSourceNodeRepo; + this.forwardNodeService = forwardNodeService; + this.applicationEventPublisher = applicationEventPublisher; + } - public Collection retrieveSourceNodes( - ForwardNodeEntity forwardNodeEntity) { - return forwardNodeService.getAllSourceNodes(forwardNodeEntity); - } + public Collection retrieveSourceNodes(ForwardNodeEntity forwardNodeEntity) { + return forwardNodeService.getAllSourceNodes(forwardNodeEntity); + } - /** - * Store given DicomSourceNodeEntity. - * - * @param forwardNodeEntity - * @param dicomSourceNodeEntity the updated or new dicomSourceNodeEntity - */ - public DicomSourceNodeEntity save( - ForwardNodeEntity forwardNodeEntity, DicomSourceNodeEntity dicomSourceNodeEntity) { - DicomSourceNodeEntity dataUpdated = - this.forwardNodeService.updateSourceNode(forwardNodeEntity, dicomSourceNodeEntity); - return dataUpdated; - } + /** + * Store given DicomSourceNodeEntity. + * @param forwardNodeEntity + * @param dicomSourceNodeEntity the updated or new dicomSourceNodeEntity + */ + public DicomSourceNodeEntity save(ForwardNodeEntity forwardNodeEntity, + DicomSourceNodeEntity dicomSourceNodeEntity) { + DicomSourceNodeEntity dataUpdated = this.forwardNodeService.updateSourceNode(forwardNodeEntity, + dicomSourceNodeEntity); + return dataUpdated; + } - /** - * Delete given data from the backing data service. - * - * @param dicomSourceNodeEntity the data to be deleted - */ - public void delete(DicomSourceNodeEntity dicomSourceNodeEntity) { - ForwardNodeEntity forwardNodeEntityOfDest = dicomSourceNodeEntity.getForwardNodeEntity(); - if (forwardNodeEntityOfDest != null) { - forwardNodeService.deleteSourceNode(forwardNodeEntityOfDest, dicomSourceNodeEntity); - } - } + /** + * Delete given data from the backing data service. + * @param dicomSourceNodeEntity the data to be deleted + */ + public void delete(DicomSourceNodeEntity dicomSourceNodeEntity) { + ForwardNodeEntity forwardNodeEntityOfDest = dicomSourceNodeEntity.getForwardNodeEntity(); + if (forwardNodeEntityOfDest != null) { + forwardNodeService.deleteSourceNode(forwardNodeEntityOfDest, dicomSourceNodeEntity); + } + } + + public ApplicationEventPublisher getApplicationEventPublisher() { + return applicationEventPublisher; + } - public ApplicationEventPublisher getApplicationEventPublisher() { - return applicationEventPublisher; - } } diff --git a/src/main/java/org/karnak/backend/service/StoreScpForwardService.java b/src/main/java/org/karnak/backend/service/StoreScpForwardService.java index 8863b8291..6edeb603f 100644 --- a/src/main/java/org/karnak/backend/service/StoreScpForwardService.java +++ b/src/main/java/org/karnak/backend/service/StoreScpForwardService.java @@ -39,118 +39,120 @@ @Service public class StoreScpForwardService { - private static final Logger LOGGER = LoggerFactory.getLogger(StoreScpForwardService.class); - - private final Device device = new Device("storescp"); - private final ApplicationEntity ae = new ApplicationEntity("*"); - private final Connection conn = new Connection(); - private volatile int priority; - private volatile int status = 0; - - private Map> destinations; - - private final CStoreSCPService cStoreSCPService; - - @Autowired - public StoreScpForwardService(final CStoreSCPService cStoreSCPService) { - this.cStoreSCPService = cStoreSCPService; - } - - /** - * Init service - * - * @param forwardParams the optional advanced parameters (proxy, authentication, connection and - * TLS) for the final destination - * @param fwdNode the calling DICOM node configuration - * @param destinationNode the final DICOM node configuration - * @param attributesEditor the editor for modifying attributes on the fly (can be Null) - */ - public void init( - AdvancedParams forwardParams, - ForwardDicomNode fwdNode, - DicomNode destinationNode, - List attributesEditor) - throws IOException { - DicomForwardDestination uniqueDestination = - new DicomForwardDestination(forwardParams, fwdNode, destinationNode, attributesEditor); - this.destinations = new HashMap<>(); - destinations.put(fwdNode, Collections.singletonList(uniqueDestination)); - cStoreSCPService.init(destinations); - - device.setDimseRQHandler(createServiceRegistry()); - device.addConnection(conn); - device.addApplicationEntity(ae); - ae.setAssociationAcceptor(true); - ae.addConnection(conn); - } - - public void init(Map> destinations) { - this.destinations = Objects.requireNonNull(destinations); - cStoreSCPService.init(destinations); - device.setDimseRQHandler(createServiceRegistry()); - device.addConnection(conn); - device.addApplicationEntity(ae); - ae.setAssociationAcceptor(true); - ae.addConnection(conn); - } - - public final void setPriority(int priority) { - this.priority = priority; - } - - private DicomServiceRegistry createServiceRegistry() { - DicomServiceRegistry serviceRegistry = new DicomServiceRegistry(); - serviceRegistry.addDicomService(new BasicCEchoSCP()); - serviceRegistry.addDicomService(cStoreSCPService); - return serviceRegistry; - } - - public void setStatus(int status) { - this.status = status; - } - - public void loadDefaultTransferCapability(URL transferCapabilityFile) { - Properties p = new Properties(); - - try { - if (transferCapabilityFile != null) { - try (InputStream in = transferCapabilityFile.openStream()) { - p.load(in); - } - } else { - p.load(this.getClass().getResourceAsStream("sop-classes.properties")); - } - } catch (IOException e) { - LOGGER.error("Cannot read sop-classes", e); - } - - for (String cuid : p.stringPropertyNames()) { - String ts = p.getProperty(cuid); - TransferCapability tc = - new TransferCapability( - null, CLIUtils.toUID(cuid), TransferCapability.Role.SCP, CLIUtils.toUIDs(ts)); - ae.addTransferCapability(tc); - } - } - - public ApplicationEntity getApplicationEntity() { - return ae; - } - - public Connection getConnection() { - return conn; - } - - public Device getDevice() { - return device; - } - - public void stop() { - destinations.values().forEach(l -> l.forEach(ForwardDestination::stop)); - cStoreSCPService.getDestinations().values().forEach(l -> l.forEach(ForwardDestination::stop)); - } - - public CStoreSCPService getCstoreSCP() { - return cStoreSCPService; - } + private static final Logger LOGGER = LoggerFactory.getLogger(StoreScpForwardService.class); + + private final Device device = new Device("storescp"); + + private final ApplicationEntity ae = new ApplicationEntity("*"); + + private final Connection conn = new Connection(); + + private volatile int priority; + + private volatile int status = 0; + + private Map> destinations; + + private final CStoreSCPService cStoreSCPService; + + @Autowired + public StoreScpForwardService(final CStoreSCPService cStoreSCPService) { + this.cStoreSCPService = cStoreSCPService; + } + + /** + * Init service + * @param forwardParams the optional advanced parameters (proxy, authentication, + * connection and TLS) for the final destination + * @param fwdNode the calling DICOM node configuration + * @param destinationNode the final DICOM node configuration + * @param attributesEditor the editor for modifying attributes on the fly (can be + * Null) + */ + public void init(AdvancedParams forwardParams, ForwardDicomNode fwdNode, DicomNode destinationNode, + List attributesEditor) throws IOException { + DicomForwardDestination uniqueDestination = new DicomForwardDestination(forwardParams, fwdNode, destinationNode, + attributesEditor); + this.destinations = new HashMap<>(); + destinations.put(fwdNode, Collections.singletonList(uniqueDestination)); + cStoreSCPService.init(destinations); + + device.setDimseRQHandler(createServiceRegistry()); + device.addConnection(conn); + device.addApplicationEntity(ae); + ae.setAssociationAcceptor(true); + ae.addConnection(conn); + } + + public void init(Map> destinations) { + this.destinations = Objects.requireNonNull(destinations); + cStoreSCPService.init(destinations); + device.setDimseRQHandler(createServiceRegistry()); + device.addConnection(conn); + device.addApplicationEntity(ae); + ae.setAssociationAcceptor(true); + ae.addConnection(conn); + } + + public final void setPriority(int priority) { + this.priority = priority; + } + + private DicomServiceRegistry createServiceRegistry() { + DicomServiceRegistry serviceRegistry = new DicomServiceRegistry(); + serviceRegistry.addDicomService(new BasicCEchoSCP()); + serviceRegistry.addDicomService(cStoreSCPService); + return serviceRegistry; + } + + public void setStatus(int status) { + this.status = status; + } + + public void loadDefaultTransferCapability(URL transferCapabilityFile) { + Properties p = new Properties(); + + try { + if (transferCapabilityFile != null) { + try (InputStream in = transferCapabilityFile.openStream()) { + p.load(in); + } + } + else { + p.load(this.getClass().getResourceAsStream("sop-classes.properties")); + } + } + catch (IOException e) { + LOGGER.error("Cannot read sop-classes", e); + } + + for (String cuid : p.stringPropertyNames()) { + String ts = p.getProperty(cuid); + TransferCapability tc = new TransferCapability(null, CLIUtils.toUID(cuid), TransferCapability.Role.SCP, + CLIUtils.toUIDs(ts)); + ae.addTransferCapability(tc); + } + } + + public ApplicationEntity getApplicationEntity() { + return ae; + } + + public Connection getConnection() { + return conn; + } + + public Device getDevice() { + return device; + } + + public void stop() { + destinations.values().forEach(l -> l.forEach(ForwardDestination::stop)); + cStoreSCPService.getDestinations().values().forEach(l -> l.forEach(ForwardDestination::stop)); + } + + public CStoreSCPService getCstoreSCP() { + return cStoreSCPService; + } + } diff --git a/src/main/java/org/karnak/backend/service/TransferMonitoringService.java b/src/main/java/org/karnak/backend/service/TransferMonitoringService.java index 8dda3b752..09b6ca529 100644 --- a/src/main/java/org/karnak/backend/service/TransferMonitoringService.java +++ b/src/main/java/org/karnak/backend/service/TransferMonitoringService.java @@ -42,145 +42,131 @@ @Service public class TransferMonitoringService { - private static final Logger LOGGER = LoggerFactory.getLogger(TransferMonitoringService.class); - - @Value("${monitoring.max-history}") - private int sizeLimit; - - // Repositories - private final TransferStatusRepo transferStatusRepo; - - @Autowired - public TransferMonitoringService(final TransferStatusRepo transferStatusRepo) { - this.transferStatusRepo = transferStatusRepo; - } - - /** - * Listener on TransferMonitoringEvent: event is saved when received - * - * @param transferMonitoringEvent TransferMonitoringEvent to save - */ - @Async - @EventListener - public void onTransferMonitoringEvent(TransferMonitoringEvent transferMonitoringEvent) { - TransferStatusEntity transferStatusEntity = - (TransferStatusEntity) transferMonitoringEvent.getSource(); - transferStatusRepo.save(transferStatusEntity); - } - - /** - * Occurs every 30 min: clean transfer_status table if over the size limit LIFO: clean oldest - * records - */ - @Scheduled(fixedRate = 30 * 60 * 1000) - public void cleanTransferStatus() { - int nbRecords = (int) transferStatusRepo.count(); - if (nbRecords > sizeLimit) { - Pageable pageable = PageRequest.of(0, nbRecords - sizeLimit); - transferStatusRepo.deleteAll(transferStatusRepo.findAllByOrderByTransferDateAsc(pageable)); - } - } - - /** - * Retrieve transfer status depending on filter and pageable - * - * @param filter Filter to evaluate - * @param pageable Pageable to evaluate - * @return Transfer status entities found - */ - public Page retrieveTransferStatusPageable( - TransferStatusFilter filter, Pageable pageable) { - Page transferStatusFound; - if (!filter.hasFilter()) { - // No filter - transferStatusFound = transferStatusRepo.findAll(pageable); - } else { - // Create the specification and query the transfer status table - Specification transferStatusSpecification = - new TransferStatusSpecification(filter); - transferStatusFound = transferStatusRepo.findAll(transferStatusSpecification, pageable); - } - return transferStatusFound; - } - - /** - * Retrieve transfer status depending on filter - * - * @param filter Filter to evaluate - * @return Transfer status entities found - */ - public List retrieveTransferStatus(TransferStatusFilter filter) { - List transferStatusFound; - if (!filter.hasFilter()) { - // No filter - transferStatusFound = transferStatusRepo.findAll(); - } else { - // Create the specification and query the transfer status table - Specification transferStatusSpecification = - new TransferStatusSpecification(filter); - transferStatusFound = transferStatusRepo.findAll(transferStatusSpecification); - } - return transferStatusFound; - } - - /** - * Count transfer status depending on filter - * - * @param filter Filter to evaluate - * @return Count of Transfer status entities found - */ - public int countTransferStatus(TransferStatusFilter filter) { - int countTransferStatus; - - if (!filter.hasFilter()) { - // No filter - countTransferStatus = (int) transferStatusRepo.count(); - } else { - // Create the specification and query the transfer status table - Specification transferStatusSpecification = - new TransferStatusSpecification(filter); - countTransferStatus = (int) transferStatusRepo.count(transferStatusSpecification); - } - return countTransferStatus; - } - - /** - * Build a transfer status csv file depending on filters - * - * @param filter Filters - * @param exportSettings Export settings - */ - public byte[] buildCsv(TransferStatusFilter filter, ExportSettings exportSettings) - throws CsvRequiredFieldEmptyException, CsvDataTypeMismatchException, IOException { - // Init outputStream + writer - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - OutputStreamWriter streamWriter = new OutputStreamWriter(stream); - CSVWriter writer = - new CSVWriter( - streamWriter, - exportSettings.getDelimiter() != null - ? exportSettings.getDelimiter().charAt(0) - : ExportSettings.DEFAULT_CSV_DELIMITER, - exportSettings.getQuoteCharacter() != null - ? exportSettings.getQuoteCharacter().charAt(0) - : CSVWriter.DEFAULT_QUOTE_CHARACTER, - CSVWriter.DEFAULT_ESCAPE_CHARACTER, - CSVWriter.DEFAULT_LINE_END); - - // Mapping strategy - MonitoringCsvMappingStrategy monitoringCsvMappingStrategy = - new MonitoringCsvMappingStrategy<>(); - - // Bean to CSV - StatefulBeanToCsv beanToCsv = - new StatefulBeanToCsvBuilder(writer) - .withMappingStrategy(monitoringCsvMappingStrategy) - .build(); - - // Write CSV - beanToCsv.write(retrieveTransferStatus(filter)); - - streamWriter.flush(); - return stream.toByteArray(); - } + private static final Logger LOGGER = LoggerFactory.getLogger(TransferMonitoringService.class); + + @Value("${monitoring.max-history}") + private int sizeLimit; + + // Repositories + private final TransferStatusRepo transferStatusRepo; + + @Autowired + public TransferMonitoringService(final TransferStatusRepo transferStatusRepo) { + this.transferStatusRepo = transferStatusRepo; + } + + /** + * Listener on TransferMonitoringEvent: event is saved when received + * @param transferMonitoringEvent TransferMonitoringEvent to save + */ + @Async + @EventListener + public void onTransferMonitoringEvent(TransferMonitoringEvent transferMonitoringEvent) { + TransferStatusEntity transferStatusEntity = (TransferStatusEntity) transferMonitoringEvent.getSource(); + transferStatusRepo.save(transferStatusEntity); + } + + /** + * Occurs every 30 min: clean transfer_status table if over the size limit LIFO: clean + * oldest records + */ + @Scheduled(fixedRate = 30 * 60 * 1000) + public void cleanTransferStatus() { + int nbRecords = (int) transferStatusRepo.count(); + if (nbRecords > sizeLimit) { + Pageable pageable = PageRequest.of(0, nbRecords - sizeLimit); + transferStatusRepo.deleteAll(transferStatusRepo.findAllByOrderByTransferDateAsc(pageable)); + } + } + + /** + * Retrieve transfer status depending on filter and pageable + * @param filter Filter to evaluate + * @param pageable Pageable to evaluate + * @return Transfer status entities found + */ + public Page retrieveTransferStatusPageable(TransferStatusFilter filter, Pageable pageable) { + Page transferStatusFound; + if (!filter.hasFilter()) { + // No filter + transferStatusFound = transferStatusRepo.findAll(pageable); + } + else { + // Create the specification and query the transfer status table + Specification transferStatusSpecification = new TransferStatusSpecification(filter); + transferStatusFound = transferStatusRepo.findAll(transferStatusSpecification, pageable); + } + return transferStatusFound; + } + + /** + * Retrieve transfer status depending on filter + * @param filter Filter to evaluate + * @return Transfer status entities found + */ + public List retrieveTransferStatus(TransferStatusFilter filter) { + List transferStatusFound; + if (!filter.hasFilter()) { + // No filter + transferStatusFound = transferStatusRepo.findAll(); + } + else { + // Create the specification and query the transfer status table + Specification transferStatusSpecification = new TransferStatusSpecification(filter); + transferStatusFound = transferStatusRepo.findAll(transferStatusSpecification); + } + return transferStatusFound; + } + + /** + * Count transfer status depending on filter + * @param filter Filter to evaluate + * @return Count of Transfer status entities found + */ + public int countTransferStatus(TransferStatusFilter filter) { + int countTransferStatus; + + if (!filter.hasFilter()) { + // No filter + countTransferStatus = (int) transferStatusRepo.count(); + } + else { + // Create the specification and query the transfer status table + Specification transferStatusSpecification = new TransferStatusSpecification(filter); + countTransferStatus = (int) transferStatusRepo.count(transferStatusSpecification); + } + return countTransferStatus; + } + + /** + * Build a transfer status csv file depending on filters + * @param filter Filters + * @param exportSettings Export settings + */ + public byte[] buildCsv(TransferStatusFilter filter, ExportSettings exportSettings) + throws CsvRequiredFieldEmptyException, CsvDataTypeMismatchException, IOException { + // Init outputStream + writer + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + OutputStreamWriter streamWriter = new OutputStreamWriter(stream); + CSVWriter writer = new CSVWriter(streamWriter, + exportSettings.getDelimiter() != null ? exportSettings.getDelimiter().charAt(0) + : ExportSettings.DEFAULT_CSV_DELIMITER, + exportSettings.getQuoteCharacter() != null ? exportSettings.getQuoteCharacter().charAt(0) + : CSVWriter.DEFAULT_QUOTE_CHARACTER, + CSVWriter.DEFAULT_ESCAPE_CHARACTER, CSVWriter.DEFAULT_LINE_END); + + // Mapping strategy + MonitoringCsvMappingStrategy monitoringCsvMappingStrategy = new MonitoringCsvMappingStrategy<>(); + + // Bean to CSV + StatefulBeanToCsv beanToCsv = new StatefulBeanToCsvBuilder(writer) + .withMappingStrategy(monitoringCsvMappingStrategy).build(); + + // Write CSV + beanToCsv.write(retrieveTransferStatus(filter)); + + streamWriter.flush(); + return stream.toByteArray(); + } + } diff --git a/src/main/java/org/karnak/backend/service/dicom/DicomEchoService.java b/src/main/java/org/karnak/backend/service/dicom/DicomEchoService.java index 87e54ef1c..d36d53fde 100644 --- a/src/main/java/org/karnak/backend/service/dicom/DicomEchoService.java +++ b/src/main/java/org/karnak/backend/service/dicom/DicomEchoService.java @@ -23,38 +23,40 @@ @Service public class DicomEchoService { - @Autowired - public DicomEchoService() {} + @Autowired + public DicomEchoService() { + } - public String dicomEcho(List nodes) throws InterruptedException, ExecutionException { - StringBuilder result = new StringBuilder(); + public String dicomEcho(List nodes) throws InterruptedException, ExecutionException { + StringBuilder result = new StringBuilder(); - List> threadsResult = createThreadsResult(nodes); - for (Future threadResult : threadsResult) { - result.append(threadResult.get()); - } + List> threadsResult = createThreadsResult(nodes); + for (Future threadResult : threadsResult) { + result.append(threadResult.get()); + } - return result.toString(); - } + return result.toString(); + } - private List> createThreadsResult(List nodes) - throws InterruptedException { - List> threadResult = null; - try { - ExecutorService executorService = Executors.newFixedThreadPool(nodes.size()); + private List> createThreadsResult(List nodes) throws InterruptedException { + List> threadResult = null; + try { + ExecutorService executorService = Executors.newFixedThreadPool(nodes.size()); - List threads = new ArrayList<>(); + List threads = new ArrayList<>(); - for (ConfigNode node : nodes) { - DicomEchoThread dicomEchoThread = new DicomEchoThread(node); - threads.add(dicomEchoThread); - } + for (ConfigNode node : nodes) { + DicomEchoThread dicomEchoThread = new DicomEchoThread(node); + threads.add(dicomEchoThread); + } - threadResult = executorService.invokeAll(threads); + threadResult = executorService.invokeAll(threads); + + return threadResult; + } + catch (InterruptedException e) { + throw e; + } + } - return threadResult; - } catch (InterruptedException e) { - throw e; - } - } } diff --git a/src/main/java/org/karnak/backend/service/dicom/WadoService.java b/src/main/java/org/karnak/backend/service/dicom/WadoService.java index ce86cbb6c..5ba5052af 100644 --- a/src/main/java/org/karnak/backend/service/dicom/WadoService.java +++ b/src/main/java/org/karnak/backend/service/dicom/WadoService.java @@ -23,30 +23,31 @@ @Service public class WadoService { - @Autowired - public WadoService() {} + @Autowired + public WadoService() { + } - public String checkWado(List nodes) throws InterruptedException, ExecutionException { - StringBuilder result = new StringBuilder(); + public String checkWado(List nodes) throws InterruptedException, ExecutionException { + StringBuilder result = new StringBuilder(); - List> threadsResult = createThreadsResult(nodes); - for (Future threadResult : threadsResult) { - result.append(threadResult.get()); - } + List> threadsResult = createThreadsResult(nodes); + for (Future threadResult : threadsResult) { + result.append(threadResult.get()); + } - return result.toString(); - } + return result.toString(); + } - private List> createThreadsResult(List nodes) - throws InterruptedException { - ExecutorService executorService = Executors.newFixedThreadPool(nodes.size()); + private List> createThreadsResult(List nodes) throws InterruptedException { + ExecutorService executorService = Executors.newFixedThreadPool(nodes.size()); - List threads = new ArrayList<>(); + List threads = new ArrayList<>(); + + for (WadoNode node : nodes) { + WadoResponse checkWadoThread = new WadoResponse(node); + threads.add(checkWadoThread); + } + return executorService.invokeAll(threads); + } - for (WadoNode node : nodes) { - WadoResponse checkWadoThread = new WadoResponse(node); - threads.add(checkWadoThread); - } - return executorService.invokeAll(threads); - } } diff --git a/src/main/java/org/karnak/backend/service/gateway/GatewayService.java b/src/main/java/org/karnak/backend/service/gateway/GatewayService.java index 62cbd9dd6..77f70c57c 100644 --- a/src/main/java/org/karnak/backend/service/gateway/GatewayService.java +++ b/src/main/java/org/karnak/backend/service/gateway/GatewayService.java @@ -33,79 +33,80 @@ @Service public class GatewayService implements ApplicationListener { - private static final Logger LOGGER = LoggerFactory.getLogger(GatewayService.class); - - private final GatewaySetUpService gatewaySetUpService; - private final DicomGatewayService gateway; - - // Repository - private final DestinationRepo destinationRepo; - - @Autowired - public GatewayService( - final GatewaySetUpService gatewaySetUpService, - final DicomGatewayService dicomGatewayService, - final DestinationRepo destinationRepo) { - this.gatewaySetUpService = gatewaySetUpService; - this.gateway = dicomGatewayService; - this.destinationRepo = destinationRepo; - } - - public void initGateway() { - try { - String[] acceptedCallingAETitles = - GatewayParams.getAcceptedCallingAETitles(gatewaySetUpService.getDestinations()); - GatewayParams gparams = - new GatewayParams( - gatewaySetUpService.getAdvancedParams(), false, null, acceptedCallingAETitles); - gateway.init(gatewaySetUpService.getDestinations()); - gateway.start(gatewaySetUpService.getCallingDicomNode(), gparams); - LOGGER.info("Karnak DICOM gateway servlet is running: {}", gatewaySetUpService); - } catch (Exception e) { - LOGGER.error("Cannot start DICOM gateway", e); - } - } - - @Override - public void onApplicationEvent(ContextRefreshedEvent event) { - LOGGER.info("Application Event: {}", event); - } - - @EventListener - public void reloadOutboundNodes(NodeEvent event) { - gatewaySetUpService.update(event); - - // Refresh the version of the gateway set up - gatewaySetUpService.refreshVersionGatewaySetUp(); - } - - @PreDestroy - public void destroy() { - if (gateway != null) { - gateway.stop(); - } - - // Reset status transfer in progress on destination - List destinationEntities = destinationRepo.findAll(); - destinationEntities.forEach(d -> d.setTransferInProgress(false)); - destinationRepo.saveAll(destinationEntities); - - LOGGER.info("{}", "Gateway has been stopped"); - String dir = System.getProperty("dicom.native.codec"); - if (StringUtil.hasText(dir)) { - FileUtil.delete(new File(dir)); - } - } - - @PostConstruct - public void init() { - LOGGER.info("{}", "Start the gateway manager running as a background process"); - try { - URL resource = this.getClass().getResource("/lib"); - NativeLibraryManager.initNativeLibs(resource); - } catch (Exception e1) { - throw new IllegalStateException("Cannot register DICOM native librairies", e1); - } - initGateway(); - } + private static final Logger LOGGER = LoggerFactory.getLogger(GatewayService.class); + + private final GatewaySetUpService gatewaySetUpService; + + private final DicomGatewayService gateway; + + // Repository + private final DestinationRepo destinationRepo; + + @Autowired + public GatewayService(final GatewaySetUpService gatewaySetUpService, final DicomGatewayService dicomGatewayService, + final DestinationRepo destinationRepo) { + this.gatewaySetUpService = gatewaySetUpService; + this.gateway = dicomGatewayService; + this.destinationRepo = destinationRepo; + } + + public void initGateway() { + try { + String[] acceptedCallingAETitles = GatewayParams + .getAcceptedCallingAETitles(gatewaySetUpService.getDestinations()); + GatewayParams gparams = new GatewayParams(gatewaySetUpService.getAdvancedParams(), false, null, + acceptedCallingAETitles); + gateway.init(gatewaySetUpService.getDestinations()); + gateway.start(gatewaySetUpService.getCallingDicomNode(), gparams); + LOGGER.info("Karnak DICOM gateway servlet is running: {}", gatewaySetUpService); + } + catch (Exception e) { + LOGGER.error("Cannot start DICOM gateway", e); + } + } + + @Override + public void onApplicationEvent(ContextRefreshedEvent event) { + LOGGER.info("Application Event: {}", event); + } + + @EventListener + public void reloadOutboundNodes(NodeEvent event) { + gatewaySetUpService.update(event); + + // Refresh the version of the gateway set up + gatewaySetUpService.refreshVersionGatewaySetUp(); + } + + @PreDestroy + public void destroy() { + if (gateway != null) { + gateway.stop(); + } + + // Reset status transfer in progress on destination + List destinationEntities = destinationRepo.findAll(); + destinationEntities.forEach(d -> d.setTransferInProgress(false)); + destinationRepo.saveAll(destinationEntities); + + LOGGER.info("{}", "Gateway has been stopped"); + String dir = System.getProperty("dicom.native.codec"); + if (StringUtil.hasText(dir)) { + FileUtil.delete(new File(dir)); + } + } + + @PostConstruct + public void init() { + LOGGER.info("{}", "Start the gateway manager running as a background process"); + try { + URL resource = this.getClass().getResource("/lib"); + NativeLibraryManager.initNativeLibs(resource); + } + catch (Exception e1) { + throw new IllegalStateException("Cannot register DICOM native librairies", e1); + } + initGateway(); + } + } diff --git a/src/main/java/org/karnak/backend/service/gateway/GatewaySetUpService.java b/src/main/java/org/karnak/backend/service/gateway/GatewaySetUpService.java index 09b856fba..1702dd646 100644 --- a/src/main/java/org/karnak/backend/service/gateway/GatewaySetUpService.java +++ b/src/main/java/org/karnak/backend/service/gateway/GatewaySetUpService.java @@ -60,409 +60,397 @@ @Service public class GatewaySetUpService { - private static final Logger LOGGER = LoggerFactory.getLogger(GatewaySetUpService.class); - // Repositories - private final ForwardNodeRepo forwardNodeRepo; - private final VersionRepo versionRepo; - private final DestinationRepo destinationRepo; - - private final Map> destMap = new HashMap<>(); - - private final Path storePath; - - private final String listenerAET; - private final int listenerPort; - private final Boolean listenerTLS; - private final int intervalCheck; - - private final String archiveUrl; - - private final String clientKey; - private final String clientKeyPwd; - private final String truststorePwd; - private final String truststore; - - // Version gateway setup for this instance - private long gatewaySetUpVersion; - - @Autowired - public GatewaySetUpService( - final ForwardNodeRepo forwardNodeRepo, - final VersionRepo versionRepo, - final DestinationRepo destinationRepo) - throws Exception { - this.forwardNodeRepo = forwardNodeRepo; - this.versionRepo = versionRepo; - this.destinationRepo = destinationRepo; - - String path = - SystemPropertyUtil.retrieveSystemProperty( - "GATEWAY_ARCHIVE_PATH", null); // Only Archive and Pull mode - storePath = StringUtil.hasText(path) ? Path.of(path) : null; - intervalCheck = - StringUtil.getInt( - SystemPropertyUtil.retrieveSystemProperty( - "GATEWAY_PULL_CHECK_INTERNAL", "5")); // Only Pull mode - archiveUrl = - SystemPropertyUtil.retrieveSystemProperty("GATEWAY_ARCHIVE_URL", ""); // Only Archive mode - - listenerAET = SystemPropertyUtil.retrieveSystemProperty("DICOM_LISTENER_AET", "KARNAK-GATEWAY"); - listenerPort = 11119; - listenerTLS = - LangUtil.getEmptytoFalse( - SystemPropertyUtil.retrieveSystemProperty("DICOM_LISTENER_TLS", null)); - - clientKey = SystemPropertyUtil.retrieveSystemProperty("TLS_KEYSTORE_PATH", null); - clientKeyPwd = SystemPropertyUtil.retrieveSystemProperty("TLS_KEYSTORE_SECRET", null); - truststorePwd = SystemPropertyUtil.retrieveSystemProperty("TLS_TRUSTSTORE_PATH", null); - truststore = SystemPropertyUtil.retrieveSystemProperty("TLS_TRUSTSTORE_SECRET", null); - - // Init the current version of the gateway setup for this instance - this.gatewaySetUpVersion = 0L; - - reloadGatewayPersistence(); - } - - private static AdvancedParams getDefaultAdvancedParameters() { - AdvancedParams params = new AdvancedParams(); - ConnectOptions connectOptions = new ConnectOptions(); - connectOptions.setConnectTimeout(5000); - connectOptions.setAcceptTimeout(7000); - // Concurrent DICOM operations - connectOptions.setMaxOpsInvoked(50); - connectOptions.setMaxOpsPerformed(50); - params.setConnectOptions(connectOptions); - return params; - } - - @Override - public String toString() { - StringBuilder buf = new StringBuilder(); - buf.append("Hostname="); - buf.append(DicomNode.convertToIP(null)); - buf.append(" AETitle="); - buf.append(listenerAET); - buf.append(" Port="); - buf.append(listenerPort); - return buf.toString(); - } - - public String getArchiveUrl() { - return archiveUrl; - } - - public Path getStorePath() { - return storePath; - } - - public String getListenerAET() { - return listenerAET; - } - - public int getListenerPort() { - return listenerPort; - } - - public Boolean getListenerTLS() { - return listenerTLS; - } - - public int getIntervalCheck() { - return intervalCheck; - } - - public String getClientKey() { - return clientKey; - } - - public String getClientKeyPwd() { - return clientKeyPwd; - } - - public String getTruststorePwd() { - return truststorePwd; - } - - public String getTruststore() { - return truststore; - } - - public AdvancedParams getAdvancedParams() { - AdvancedParams options = getDefaultAdvancedParameters(); - ConnectOptions connectOptions = options.getConnectOptions(); - if (getListenerTLS()) { - TlsOptions tls = - new TlsOptions( - false, - getClientKey(), - "JKS", - getClientKeyPwd(), - getClientKeyPwd(), - getTruststore(), - "JKS", - getTruststorePwd()); - options.setTlsOptions(tls); - } - options.setConnectOptions(connectOptions); - return options; - } - - public DicomNode getCallingDicomNode() { - return new DicomNode(getListenerAET(), null, getListenerPort()); - } - - public Optional getDestinationNode(String fwdAET) { - return destMap.keySet().stream().filter(n -> n.getForwardAETitle().equals(fwdAET)).findFirst(); - } - - public List getDestination(String fwdAET) { - Optional node = getDestinationNode(fwdAET); - node.ifPresent(this::getDestinations); - return Collections.emptyList(); - } - - public List getDestinations(ForwardDicomNode fwdSrcNode) { - List destList = null; - if (fwdSrcNode != null) { - destList = destMap.get(fwdSrcNode); - } - if (destList == null) { - return Collections.emptyList(); - } - return destList; - } - - public Map> getDestinations() { - return destMap; - } - - public Set getKeys() { - return destMap.keySet(); - } - - private void addDestinationNode( - List dstList, ForwardDicomNode fwdSrcNode, DestinationEntity dstNode) { - try { - List editors = new ArrayList<>(); - - if (!dstNode.getCondition().isEmpty()) { - editors.add(new ConditionEditor(dstNode.getCondition())); - } - - final boolean filterBySOPClassesEnable = dstNode.isFilterBySOPClasses(); - if (filterBySOPClassesEnable) { - editors.add(new FilterEditor(dstNode.getSOPClassUIDEntityFilters())); - } - - final List kheopsAlbumEntities = dstNode.getKheopsAlbumEntities(); - - SwitchingAlbum switchingAlbum = new SwitchingAlbum(); - if (kheopsAlbumEntities != null && !kheopsAlbumEntities.isEmpty()) { - editors.add( - (Attributes dcm, AttributeEditorContext context) -> { - kheopsAlbumEntities.forEach( - kheopsAlbums -> { - switchingAlbum.apply(dstNode, kheopsAlbums, dcm); - }); - }); - } - - StreamRegistryEditor streamRegistryEditor = new StreamRegistryEditor(); - editors.add(streamRegistryEditor); - - boolean deidentificationEnable = dstNode.isDesidentification(); - boolean profileDefined = - dstNode.getProjectEntity() != null - && dstNode.getProjectEntity().getProfileEntity() != null; - if (deidentificationEnable && profileDefined) { // TODO add an option in destination model - editors.add(new DeIdentifyEditor(dstNode)); - } - - DicomProgress progress = new DicomProgress(); - - if (dstNode.isActivate()) { - if (dstNode.getDestinationType() == DestinationType.stow) { - // parse headers to hashmap - HashMap map = new HashMap<>(); - String headers = dstNode.getHeaders(); - Document doc = Jsoup.parse(headers); - String key = doc.getElementsByTag("key").text(); - String value = doc.getElementsByTag("value").text(); - if (StringUtil.hasText(key)) { - map.put(key, value); - } - - WebForwardDestination fwd = - new WebForwardDestination( - dstNode.getId(), - fwdSrcNode, - dstNode.getUrl(), - map, - progress, - editors, - dstNode.getTransferSyntax(), - dstNode.isTranscodeOnlyUncompressed()); - - if (kheopsAlbumEntities != null && !kheopsAlbumEntities.isEmpty()) { - progress.addProgressListener( - (DicomProgress dicomProgress) -> { - Attributes dcm = dicomProgress.getAttributes(); - kheopsAlbumEntities.forEach( - kheopsAlbums -> { - switchingAlbum.applyAfterTransfer(kheopsAlbums, dcm); - }); - }); - } - dstList.add(fwd); - } else { - DicomNode destinationNode = - new DicomNode(dstNode.getAeTitle(), dstNode.getHostname(), dstNode.getPort()); - DicomForwardDestination dest = - new DicomForwardDestination( - dstNode.getId(), - getDefaultAdvancedParameters(), - fwdSrcNode, - destinationNode, - dstNode.getUseaetdest(), - progress, - editors, - dstNode.getTransferSyntax(), - dstNode.isTranscodeOnlyUncompressed()); - - dstList.add(dest); - } - } - } catch (IOException e) { - LOGGER.error("Cannot build ForwardDestination", e); - } - } - - public void reloadGatewayPersistence() { - - List list = new ArrayList<>(forwardNodeRepo.findAll()); - for (ForwardNodeEntity forwardNodeEntity : list) { - ForwardDicomNode fwdSrcNode = - new ForwardDicomNode(forwardNodeEntity.getFwdAeTitle(), null, forwardNodeEntity.getId()); - addAcceptedSourceNodes(fwdSrcNode, forwardNodeEntity); - List dstList = - new ArrayList<>(forwardNodeEntity.getDestinationEntities().size()); - for (DestinationEntity dstNode : forwardNodeEntity.getDestinationEntities()) { - addDestinationNode(dstList, fwdSrcNode, dstNode); - } - destMap.put(fwdSrcNode, dstList); - } - } - - public void update(NodeEvent event) { - NodeEventType type = event.getEventType(); - Object src = event.getSource(); - Long id = event.getForwardNode().getId(); - String aet = event.getForwardNode().getFwdAeTitle(); - Optional val = - destMap.keySet().stream().filter(f -> id.equals(f.getId())).findFirst(); - ForwardDicomNode fwdNode; - if (val.isEmpty()) { - fwdNode = new ForwardDicomNode(aet, null, id); - destMap.put(fwdNode, new ArrayList<>(2)); - } else { - fwdNode = val.get(); - } - if (src instanceof DicomSourceNodeEntity) { - DicomSourceNodeEntity srcNode = (DicomSourceNodeEntity) src; - if (type == NodeEventType.ADD) { - fwdNode.addAcceptedSourceNode(srcNode.getId(), srcNode.getAeTitle(), srcNode.getHostname()); - } else if (type == NodeEventType.REMOVE) { - fwdNode.getAcceptedSourceNodes().removeIf(s -> srcNode.getId().equals(s.getId())); - } else if (type == NodeEventType.UPDATE) { - fwdNode.getAcceptedSourceNodes().removeIf(s -> srcNode.getId().equals(s.getId())); - fwdNode.addAcceptedSourceNode(srcNode.getId(), srcNode.getAeTitle(), srcNode.getHostname()); - } - } else if (src instanceof DestinationEntity) { - DestinationEntity dstNode = (DestinationEntity) src; - if (type == NodeEventType.ADD) { - addDestinationNode(destMap.get(fwdNode), fwdNode, dstNode); - } else if (type == NodeEventType.REMOVE) { - destMap.get(fwdNode).removeIf(d -> dstNode.getId().equals(d.getId())); - } else if (type == NodeEventType.UPDATE) { - destMap.get(fwdNode).removeIf(d -> dstNode.getId().equals(d.getId())); - addDestinationNode(destMap.get(fwdNode), fwdNode, dstNode); - } - } else if (src instanceof ForwardNodeEntity) { - ForwardNodeEntity fw = (ForwardNodeEntity) src; - if (type == NodeEventType.ADD) { - addAcceptedSourceNodes(fwdNode, fw); - destMap.put(fwdNode, addDestinationNodes(fwdNode, fw)); - } else if (type == NodeEventType.REMOVE) { - destMap.remove(fwdNode); - } else if (type == NodeEventType.UPDATE) { - if (!aet.equals(fwdNode.getAet())) { - ForwardDicomNode newfwdNode = new ForwardDicomNode(aet, null, id); - for (DicomNode srcNode : fwdNode.getAcceptedSourceNodes()) { - newfwdNode.getAcceptedSourceNodes().add(srcNode); - } - destMap.put(newfwdNode, destMap.remove(fwdNode)); - } - } - } else { - reloadGatewayPersistence(); - } - } - - private void addAcceptedSourceNodes( - ForwardDicomNode fwdSrcNode, ForwardNodeEntity forwardNodeEntity) { - for (DicomSourceNodeEntity srcNode : forwardNodeEntity.getSourceNodes()) { - fwdSrcNode.addAcceptedSourceNode( - srcNode.getId(), srcNode.getAeTitle(), srcNode.getHostname()); - } - } - - private List addDestinationNodes( - ForwardDicomNode fwdSrcNode, ForwardNodeEntity forwardNodeEntity) { - List dstList = - new ArrayList<>(forwardNodeEntity.getDestinationEntities().size()); - for (DestinationEntity dstNode : forwardNodeEntity.getDestinationEntities()) { - addDestinationNode(dstList, fwdSrcNode, dstNode); - } - return dstList; - } - - /** - * When an event on the gateway setup occurs, increment the version in order for other instance to - * be notified that a refresh of the configuration should be done - */ - public void refreshVersionGatewaySetUp() { - // Retrieve the last version to increment - VersionEntity lastVersion = versionRepo.findTopByOrderByIdDesc(); - if (lastVersion == null) { - // Case nothing in DB - lastVersion = new VersionEntity(); - } - // Increment and save the version - lastVersion.setGatewaySetup(lastVersion.getGatewaySetup() + 1); - versionRepo.save(lastVersion); - - // Update the current instance version - gatewaySetUpVersion = lastVersion.getGatewaySetup(); - } - - /** Check if a refresh of the configuration should be done */ - @Scheduled(fixedRate = 5000) - private void checkRefreshGatewaySetUp() { - // Retrieve last gateway version - VersionEntity lastVersion = versionRepo.findTopByOrderByIdDesc(); - - // Check if refresh needed: current version of the gateway setup for this instance is lower than - // the last version in DB - if (lastVersion != null && gatewaySetUpVersion < lastVersion.getGatewaySetup()) { - // Check no transfer is in progress - if (destinationRepo.findAll().stream().noneMatch(DestinationEntity::isTransferInProgress)) { - // Rebuild the configuration - destMap.clear(); - reloadGatewayPersistence(); - - // Update the current instance version - gatewaySetUpVersion = lastVersion.getGatewaySetup(); - } - } - } + private static final Logger LOGGER = LoggerFactory.getLogger(GatewaySetUpService.class); + + // Repositories + private final ForwardNodeRepo forwardNodeRepo; + + private final VersionRepo versionRepo; + + private final DestinationRepo destinationRepo; + + private final Map> destMap = new HashMap<>(); + + private final Path storePath; + + private final String listenerAET; + + private final int listenerPort; + + private final Boolean listenerTLS; + + private final int intervalCheck; + + private final String archiveUrl; + + private final String clientKey; + + private final String clientKeyPwd; + + private final String truststorePwd; + + private final String truststore; + + // Version gateway setup for this instance + private long gatewaySetUpVersion; + + @Autowired + public GatewaySetUpService(final ForwardNodeRepo forwardNodeRepo, final VersionRepo versionRepo, + final DestinationRepo destinationRepo) throws Exception { + this.forwardNodeRepo = forwardNodeRepo; + this.versionRepo = versionRepo; + this.destinationRepo = destinationRepo; + + String path = SystemPropertyUtil.retrieveSystemProperty("GATEWAY_ARCHIVE_PATH", null); // Only + // Archive + // and + // Pull + // mode + storePath = StringUtil.hasText(path) ? Path.of(path) : null; + intervalCheck = StringUtil + .getInt(SystemPropertyUtil.retrieveSystemProperty("GATEWAY_PULL_CHECK_INTERNAL", "5")); // Only + // Pull + // mode + archiveUrl = SystemPropertyUtil.retrieveSystemProperty("GATEWAY_ARCHIVE_URL", ""); // Only + // Archive + // mode + + listenerAET = SystemPropertyUtil.retrieveSystemProperty("DICOM_LISTENER_AET", "KARNAK-GATEWAY"); + listenerPort = 11119; + listenerTLS = LangUtil.getEmptytoFalse(SystemPropertyUtil.retrieveSystemProperty("DICOM_LISTENER_TLS", null)); + + clientKey = SystemPropertyUtil.retrieveSystemProperty("TLS_KEYSTORE_PATH", null); + clientKeyPwd = SystemPropertyUtil.retrieveSystemProperty("TLS_KEYSTORE_SECRET", null); + truststorePwd = SystemPropertyUtil.retrieveSystemProperty("TLS_TRUSTSTORE_PATH", null); + truststore = SystemPropertyUtil.retrieveSystemProperty("TLS_TRUSTSTORE_SECRET", null); + + // Init the current version of the gateway setup for this instance + this.gatewaySetUpVersion = 0L; + + reloadGatewayPersistence(); + } + + private static AdvancedParams getDefaultAdvancedParameters() { + AdvancedParams params = new AdvancedParams(); + ConnectOptions connectOptions = new ConnectOptions(); + connectOptions.setConnectTimeout(5000); + connectOptions.setAcceptTimeout(7000); + // Concurrent DICOM operations + connectOptions.setMaxOpsInvoked(50); + connectOptions.setMaxOpsPerformed(50); + params.setConnectOptions(connectOptions); + return params; + } + + @Override + public String toString() { + StringBuilder buf = new StringBuilder(); + buf.append("Hostname="); + buf.append(DicomNode.convertToIP(null)); + buf.append(" AETitle="); + buf.append(listenerAET); + buf.append(" Port="); + buf.append(listenerPort); + return buf.toString(); + } + + public String getArchiveUrl() { + return archiveUrl; + } + + public Path getStorePath() { + return storePath; + } + + public String getListenerAET() { + return listenerAET; + } + + public int getListenerPort() { + return listenerPort; + } + + public Boolean getListenerTLS() { + return listenerTLS; + } + + public int getIntervalCheck() { + return intervalCheck; + } + + public String getClientKey() { + return clientKey; + } + + public String getClientKeyPwd() { + return clientKeyPwd; + } + + public String getTruststorePwd() { + return truststorePwd; + } + + public String getTruststore() { + return truststore; + } + + public AdvancedParams getAdvancedParams() { + AdvancedParams options = getDefaultAdvancedParameters(); + ConnectOptions connectOptions = options.getConnectOptions(); + if (getListenerTLS()) { + TlsOptions tls = new TlsOptions(false, getClientKey(), "JKS", getClientKeyPwd(), getClientKeyPwd(), + getTruststore(), "JKS", getTruststorePwd()); + options.setTlsOptions(tls); + } + options.setConnectOptions(connectOptions); + return options; + } + + public DicomNode getCallingDicomNode() { + return new DicomNode(getListenerAET(), null, getListenerPort()); + } + + public Optional getDestinationNode(String fwdAET) { + return destMap.keySet().stream().filter(n -> n.getForwardAETitle().equals(fwdAET)).findFirst(); + } + + public List getDestination(String fwdAET) { + Optional node = getDestinationNode(fwdAET); + node.ifPresent(this::getDestinations); + return Collections.emptyList(); + } + + public List getDestinations(ForwardDicomNode fwdSrcNode) { + List destList = null; + if (fwdSrcNode != null) { + destList = destMap.get(fwdSrcNode); + } + if (destList == null) { + return Collections.emptyList(); + } + return destList; + } + + public Map> getDestinations() { + return destMap; + } + + public Set getKeys() { + return destMap.keySet(); + } + + private void addDestinationNode(List dstList, ForwardDicomNode fwdSrcNode, + DestinationEntity dstNode) { + try { + List editors = new ArrayList<>(); + + if (!dstNode.getCondition().isEmpty()) { + editors.add(new ConditionEditor(dstNode.getCondition())); + } + + final boolean filterBySOPClassesEnable = dstNode.isFilterBySOPClasses(); + if (filterBySOPClassesEnable) { + editors.add(new FilterEditor(dstNode.getSOPClassUIDEntityFilters())); + } + + final List kheopsAlbumEntities = dstNode.getKheopsAlbumEntities(); + + SwitchingAlbum switchingAlbum = new SwitchingAlbum(); + if (kheopsAlbumEntities != null && !kheopsAlbumEntities.isEmpty()) { + editors.add((Attributes dcm, AttributeEditorContext context) -> { + kheopsAlbumEntities.forEach(kheopsAlbums -> { + switchingAlbum.apply(dstNode, kheopsAlbums, dcm); + }); + }); + } + + StreamRegistryEditor streamRegistryEditor = new StreamRegistryEditor(); + editors.add(streamRegistryEditor); + + boolean deidentificationEnable = dstNode.isDesidentification(); + boolean profileDefined = dstNode.getProjectEntity() != null + && dstNode.getProjectEntity().getProfileEntity() != null; + if (deidentificationEnable && profileDefined) { // TODO add an option in + // destination model + editors.add(new DeIdentifyEditor(dstNode)); + } + + DicomProgress progress = new DicomProgress(); + + if (dstNode.isActivate()) { + if (dstNode.getDestinationType() == DestinationType.stow) { + // parse headers to hashmap + HashMap map = new HashMap<>(); + String headers = dstNode.getHeaders(); + Document doc = Jsoup.parse(headers); + String key = doc.getElementsByTag("key").text(); + String value = doc.getElementsByTag("value").text(); + if (StringUtil.hasText(key)) { + map.put(key, value); + } + + WebForwardDestination fwd = new WebForwardDestination(dstNode.getId(), fwdSrcNode, dstNode.getUrl(), + map, progress, editors, dstNode.getTransferSyntax(), dstNode.isTranscodeOnlyUncompressed()); + + if (kheopsAlbumEntities != null && !kheopsAlbumEntities.isEmpty()) { + progress.addProgressListener((DicomProgress dicomProgress) -> { + Attributes dcm = dicomProgress.getAttributes(); + kheopsAlbumEntities.forEach(kheopsAlbums -> { + switchingAlbum.applyAfterTransfer(kheopsAlbums, dcm); + }); + }); + } + dstList.add(fwd); + } + else { + DicomNode destinationNode = new DicomNode(dstNode.getAeTitle(), dstNode.getHostname(), + dstNode.getPort()); + DicomForwardDestination dest = new DicomForwardDestination(dstNode.getId(), + getDefaultAdvancedParameters(), fwdSrcNode, destinationNode, dstNode.getUseaetdest(), + progress, editors, dstNode.getTransferSyntax(), dstNode.isTranscodeOnlyUncompressed()); + + dstList.add(dest); + } + } + } + catch (IOException e) { + LOGGER.error("Cannot build ForwardDestination", e); + } + } + + public void reloadGatewayPersistence() { + + List list = new ArrayList<>(forwardNodeRepo.findAll()); + for (ForwardNodeEntity forwardNodeEntity : list) { + ForwardDicomNode fwdSrcNode = new ForwardDicomNode(forwardNodeEntity.getFwdAeTitle(), null, + forwardNodeEntity.getId()); + addAcceptedSourceNodes(fwdSrcNode, forwardNodeEntity); + List dstList = new ArrayList<>(forwardNodeEntity.getDestinationEntities().size()); + for (DestinationEntity dstNode : forwardNodeEntity.getDestinationEntities()) { + addDestinationNode(dstList, fwdSrcNode, dstNode); + } + destMap.put(fwdSrcNode, dstList); + } + } + + public void update(NodeEvent event) { + NodeEventType type = event.getEventType(); + Object src = event.getSource(); + Long id = event.getForwardNode().getId(); + String aet = event.getForwardNode().getFwdAeTitle(); + Optional val = destMap.keySet().stream().filter(f -> id.equals(f.getId())).findFirst(); + ForwardDicomNode fwdNode; + if (val.isEmpty()) { + fwdNode = new ForwardDicomNode(aet, null, id); + destMap.put(fwdNode, new ArrayList<>(2)); + } + else { + fwdNode = val.get(); + } + if (src instanceof DicomSourceNodeEntity) { + DicomSourceNodeEntity srcNode = (DicomSourceNodeEntity) src; + if (type == NodeEventType.ADD) { + fwdNode.addAcceptedSourceNode(srcNode.getId(), srcNode.getAeTitle(), srcNode.getHostname()); + } + else if (type == NodeEventType.REMOVE) { + fwdNode.getAcceptedSourceNodes().removeIf(s -> srcNode.getId().equals(s.getId())); + } + else if (type == NodeEventType.UPDATE) { + fwdNode.getAcceptedSourceNodes().removeIf(s -> srcNode.getId().equals(s.getId())); + fwdNode.addAcceptedSourceNode(srcNode.getId(), srcNode.getAeTitle(), srcNode.getHostname()); + } + } + else if (src instanceof DestinationEntity) { + DestinationEntity dstNode = (DestinationEntity) src; + if (type == NodeEventType.ADD) { + addDestinationNode(destMap.get(fwdNode), fwdNode, dstNode); + } + else if (type == NodeEventType.REMOVE) { + destMap.get(fwdNode).removeIf(d -> dstNode.getId().equals(d.getId())); + } + else if (type == NodeEventType.UPDATE) { + destMap.get(fwdNode).removeIf(d -> dstNode.getId().equals(d.getId())); + addDestinationNode(destMap.get(fwdNode), fwdNode, dstNode); + } + } + else if (src instanceof ForwardNodeEntity) { + ForwardNodeEntity fw = (ForwardNodeEntity) src; + if (type == NodeEventType.ADD) { + addAcceptedSourceNodes(fwdNode, fw); + destMap.put(fwdNode, addDestinationNodes(fwdNode, fw)); + } + else if (type == NodeEventType.REMOVE) { + destMap.remove(fwdNode); + } + else if (type == NodeEventType.UPDATE) { + if (!aet.equals(fwdNode.getAet())) { + ForwardDicomNode newfwdNode = new ForwardDicomNode(aet, null, id); + for (DicomNode srcNode : fwdNode.getAcceptedSourceNodes()) { + newfwdNode.getAcceptedSourceNodes().add(srcNode); + } + destMap.put(newfwdNode, destMap.remove(fwdNode)); + } + } + } + else { + reloadGatewayPersistence(); + } + } + + private void addAcceptedSourceNodes(ForwardDicomNode fwdSrcNode, ForwardNodeEntity forwardNodeEntity) { + for (DicomSourceNodeEntity srcNode : forwardNodeEntity.getSourceNodes()) { + fwdSrcNode.addAcceptedSourceNode(srcNode.getId(), srcNode.getAeTitle(), srcNode.getHostname()); + } + } + + private List addDestinationNodes(ForwardDicomNode fwdSrcNode, + ForwardNodeEntity forwardNodeEntity) { + List dstList = new ArrayList<>(forwardNodeEntity.getDestinationEntities().size()); + for (DestinationEntity dstNode : forwardNodeEntity.getDestinationEntities()) { + addDestinationNode(dstList, fwdSrcNode, dstNode); + } + return dstList; + } + + /** + * When an event on the gateway setup occurs, increment the version in order for other + * instance to be notified that a refresh of the configuration should be done + */ + public void refreshVersionGatewaySetUp() { + // Retrieve the last version to increment + VersionEntity lastVersion = versionRepo.findTopByOrderByIdDesc(); + if (lastVersion == null) { + // Case nothing in DB + lastVersion = new VersionEntity(); + } + // Increment and save the version + lastVersion.setGatewaySetup(lastVersion.getGatewaySetup() + 1); + versionRepo.save(lastVersion); + + // Update the current instance version + gatewaySetUpVersion = lastVersion.getGatewaySetup(); + } + + /** Check if a refresh of the configuration should be done */ + @Scheduled(fixedRate = 5000) + private void checkRefreshGatewaySetUp() { + // Retrieve last gateway version + VersionEntity lastVersion = versionRepo.findTopByOrderByIdDesc(); + + // Check if refresh needed: current version of the gateway setup for this instance + // is lower than + // the last version in DB + if (lastVersion != null && gatewaySetUpVersion < lastVersion.getGatewaySetup()) { + // Check no transfer is in progress + if (destinationRepo.findAll().stream().noneMatch(DestinationEntity::isTransferInProgress)) { + // Rebuild the configuration + destMap.clear(); + reloadGatewayPersistence(); + + // Update the current instance version + gatewaySetUpVersion = lastVersion.getGatewaySetup(); + } + } + } + } diff --git a/src/main/java/org/karnak/backend/service/kheops/SwitchingAlbum.java b/src/main/java/org/karnak/backend/service/kheops/SwitchingAlbum.java index c6cbf7b1c..140ef6684 100644 --- a/src/main/java/org/karnak/backend/service/kheops/SwitchingAlbum.java +++ b/src/main/java/org/karnak/backend/service/kheops/SwitchingAlbum.java @@ -37,193 +37,167 @@ public class SwitchingAlbum { - public static final ImmutableList MIN_SCOPE_SOURCE = ImmutableList.of("read", "send"); - public static final ImmutableList MIN_SCOPE_DESTINATION = ImmutableList.of("write"); - private static final Logger LOGGER = LoggerFactory.getLogger(SwitchingAlbum.class); - private final KheopsApi kheopsAPI; - private final Map switchingAlbumToDo = new WeakHashMap<>(); - - public SwitchingAlbum() { - kheopsAPI = new KheopsApi(); - } - - private static HMAC generateHMAC(DestinationEntity destinationEntity) { - if (destinationEntity.isDesidentification()) { - ProjectEntity projectEntity = destinationEntity.getProjectEntity(); - SecretEntity secretEntity = projectEntity.retrieveActiveSecret(); - return secretEntity != null ? new HMAC(secretEntity.getKey()) : null; - } - return null; - } - - private static String hashUIDonDeidentification( - DestinationEntity destinationEntity, String inputUID, HMAC hmac, int tag) { - ActionItem action = getAction(destinationEntity, tag); - if (destinationEntity.isDesidentification() && hmac != null && action instanceof UID) { - return hmac.uidHash(inputUID); - } - return inputUID; - } - - private static boolean validateCondition(String condition, Attributes dcm) { - final ExprCondition conditionKheops = new ExprCondition(dcm); - return (Boolean) ExpressionResult.get(condition, conditionKheops, Boolean.class); - } - - public static boolean validateIntrospectedToken( - JSONObject introspectObject, List validMinScope) { - boolean valid = true; - if (!introspectObject.getBoolean("active")) { - return false; - } - final String scope = introspectObject.getString("scope"); - for (String minScope : validMinScope) { - valid = scope.contains(minScope) && valid; - } - return valid; - } - - public static ActionItem getAction(DestinationEntity destinationEntity, int tag) { - if (destinationEntity.getProjectEntity() != null - && destinationEntity.getProjectEntity().getProfileEntity() != null) { - List profileItems = - Profile.getProfileItems(destinationEntity.getProjectEntity().getProfileEntity()); - for (ProfileItem profileItem : - profileItems.stream() - .filter(p -> !(p instanceof CleanPixelData)) - .collect(Collectors.toList())) { - try { - ActionItem action = - profileItem.getAction( - new Attributes(), new Attributes(), tag, new HMAC(HMAC.generateRandomKey())); - if (action != null) { - return action; - } - } catch (Exception e) { - LOGGER.error( - "Switching KHEOPS, cannot get action for the destination: {}", - destinationEntity.getDescription(), - e); - } - } - } - return null; - } - - public void apply( - DestinationEntity destinationEntity, KheopsAlbumsEntity kheopsAlbumsEntity, Attributes dcm) { - String authorizationSource = kheopsAlbumsEntity.getAuthorizationSource(); - String authorizationDestination = kheopsAlbumsEntity.getAuthorizationDestination(); - String condition = kheopsAlbumsEntity.getCondition(); - HMAC hmac = generateHMAC(destinationEntity); - String studyInstanceUID = - hashUIDonDeidentification( - destinationEntity, dcm.getString(Tag.StudyInstanceUID), hmac, Tag.StudyInstanceUID); - String seriesInstanceUID = - hashUIDonDeidentification( - destinationEntity, dcm.getString(Tag.SeriesInstanceUID), hmac, Tag.SeriesInstanceUID); - String sopInstanceUID = dcm.getString(Tag.SOPInstanceUID); - String urlAPI = kheopsAlbumsEntity.getUrlAPI(); - Long id = kheopsAlbumsEntity.getId(); - if (!switchingAlbumToDo.containsKey(id)) { - switchingAlbumToDo.put(id, new ArrayList()); - } - ArrayList metadataToDo = - (ArrayList) switchingAlbumToDo.get(id); - - if ((condition == null || condition.length() == 0 || validateCondition(condition, dcm)) - && metadataToDo.stream() - .noneMatch( - metadataSwitching -> - metadataSwitching.getSeriesInstanceUID().equals(seriesInstanceUID))) { - final boolean validAuthorizationSource = - validateToken(MIN_SCOPE_SOURCE, urlAPI, authorizationSource); - final boolean validDestinationSource = - validateToken(MIN_SCOPE_DESTINATION, urlAPI, authorizationDestination); - - if (validAuthorizationSource && validDestinationSource) { - metadataToDo.add( - new MetadataSwitching(studyInstanceUID, seriesInstanceUID, sopInstanceUID)); - } else { - LOGGER.warn( - "Can't validate a token for switching KHEOPS album [{}]. The series [{}] won't be shared.", - kheopsAlbumsEntity.getId(), - seriesInstanceUID); - } - } - } - - private boolean validateToken(List validMinScope, String urlAPI, String introspectToken) { - try { - JSONObject responseIntrospect = - kheopsAPI.tokenIntrospect(urlAPI, introspectToken, introspectToken); - return validateIntrospectedToken(responseIntrospect, validMinScope); - } catch (InterruptedException e) { - LOGGER.warn("Session interrupted", e); - Thread.currentThread().interrupt(); - } catch (Exception e) { - LOGGER.error("Invalid token", e); - } - return false; - } - - public void applyAfterTransfer(KheopsAlbumsEntity kheopsAlbumsEntity, Attributes dcm) { - String sopInstanceUID = dcm.getString(Tag.AffectedSOPInstanceUID); - if (sopInstanceUID == null) { - throw new IllegalStateException("AffectedSOPInstanceUID not found"); - } - Long id = kheopsAlbumsEntity.getId(); - String authorizationSource = kheopsAlbumsEntity.getAuthorizationSource(); - String authorizationDestination = kheopsAlbumsEntity.getAuthorizationDestination(); - String urlAPI = kheopsAlbumsEntity.getUrlAPI(); - - ArrayList metadataToDo = - (ArrayList) switchingAlbumToDo.get(id); - metadataToDo.forEach( - metadataSwitching -> { - if (metadataSwitching.getSOPinstanceUID().equals(sopInstanceUID) - && !metadataSwitching.isApplied()) { - int status = - shareSerie( - urlAPI, - metadataSwitching.getStudyInstanceUID(), - metadataSwitching.getSeriesInstanceUID(), - authorizationSource, - authorizationDestination); - if (status >= 400 && status <= 599) { - LOGGER.warn( - "Can't share the serie [{}] for switching KHEOPS album [{}]. The response status is {}", - metadataSwitching.getSeriesInstanceUID(), - id, - status); - metadataSwitching.setApplied(false); - } else { - metadataSwitching.setApplied(true); - } - } - }); - } - - private int shareSerie( - String urlAPI, - String studyInstanceUID, - String seriesInstanceUID, - String authorizationSource, - String authorizationDestination) { - try { - return kheopsAPI.shareSerie( - studyInstanceUID, - seriesInstanceUID, - urlAPI, - authorizationSource, - authorizationDestination); - } catch (InterruptedException e) { - LOGGER.warn("Session interrupted", e); - Thread.currentThread().interrupt(); - } catch (Exception e) { - LOGGER.error( - "Can't share the serie {} in the study {}", seriesInstanceUID, studyInstanceUID, e); - } - return -1; - } + public static final ImmutableList MIN_SCOPE_SOURCE = ImmutableList.of("read", "send"); + + public static final ImmutableList MIN_SCOPE_DESTINATION = ImmutableList.of("write"); + + private static final Logger LOGGER = LoggerFactory.getLogger(SwitchingAlbum.class); + + private final KheopsApi kheopsAPI; + + private final Map switchingAlbumToDo = new WeakHashMap<>(); + + public SwitchingAlbum() { + kheopsAPI = new KheopsApi(); + } + + private static HMAC generateHMAC(DestinationEntity destinationEntity) { + if (destinationEntity.isDesidentification()) { + ProjectEntity projectEntity = destinationEntity.getProjectEntity(); + SecretEntity secretEntity = projectEntity.retrieveActiveSecret(); + return secretEntity != null ? new HMAC(secretEntity.getKey()) : null; + } + return null; + } + + private static String hashUIDonDeidentification(DestinationEntity destinationEntity, String inputUID, HMAC hmac, + int tag) { + ActionItem action = getAction(destinationEntity, tag); + if (destinationEntity.isDesidentification() && hmac != null && action instanceof UID) { + return hmac.uidHash(inputUID); + } + return inputUID; + } + + private static boolean validateCondition(String condition, Attributes dcm) { + final ExprCondition conditionKheops = new ExprCondition(dcm); + return (Boolean) ExpressionResult.get(condition, conditionKheops, Boolean.class); + } + + public static boolean validateIntrospectedToken(JSONObject introspectObject, List validMinScope) { + boolean valid = true; + if (!introspectObject.getBoolean("active")) { + return false; + } + final String scope = introspectObject.getString("scope"); + for (String minScope : validMinScope) { + valid = scope.contains(minScope) && valid; + } + return valid; + } + + public static ActionItem getAction(DestinationEntity destinationEntity, int tag) { + if (destinationEntity.getProjectEntity() != null + && destinationEntity.getProjectEntity().getProfileEntity() != null) { + List profileItems = Profile + .getProfileItems(destinationEntity.getProjectEntity().getProfileEntity()); + for (ProfileItem profileItem : profileItems.stream().filter(p -> !(p instanceof CleanPixelData)) + .collect(Collectors.toList())) { + try { + ActionItem action = profileItem.getAction(new Attributes(), new Attributes(), tag, + new HMAC(HMAC.generateRandomKey())); + if (action != null) { + return action; + } + } + catch (Exception e) { + LOGGER.error("Switching KHEOPS, cannot get action for the destination: {}", + destinationEntity.getDescription(), e); + } + } + } + return null; + } + + public void apply(DestinationEntity destinationEntity, KheopsAlbumsEntity kheopsAlbumsEntity, Attributes dcm) { + String authorizationSource = kheopsAlbumsEntity.getAuthorizationSource(); + String authorizationDestination = kheopsAlbumsEntity.getAuthorizationDestination(); + String condition = kheopsAlbumsEntity.getCondition(); + HMAC hmac = generateHMAC(destinationEntity); + String studyInstanceUID = hashUIDonDeidentification(destinationEntity, dcm.getString(Tag.StudyInstanceUID), + hmac, Tag.StudyInstanceUID); + String seriesInstanceUID = hashUIDonDeidentification(destinationEntity, dcm.getString(Tag.SeriesInstanceUID), + hmac, Tag.SeriesInstanceUID); + String sopInstanceUID = dcm.getString(Tag.SOPInstanceUID); + String urlAPI = kheopsAlbumsEntity.getUrlAPI(); + Long id = kheopsAlbumsEntity.getId(); + if (!switchingAlbumToDo.containsKey(id)) { + switchingAlbumToDo.put(id, new ArrayList()); + } + ArrayList metadataToDo = (ArrayList) switchingAlbumToDo.get(id); + + if ((condition == null || condition.length() == 0 || validateCondition(condition, dcm)) && metadataToDo.stream() + .noneMatch(metadataSwitching -> metadataSwitching.getSeriesInstanceUID().equals(seriesInstanceUID))) { + final boolean validAuthorizationSource = validateToken(MIN_SCOPE_SOURCE, urlAPI, authorizationSource); + final boolean validDestinationSource = validateToken(MIN_SCOPE_DESTINATION, urlAPI, + authorizationDestination); + + if (validAuthorizationSource && validDestinationSource) { + metadataToDo.add(new MetadataSwitching(studyInstanceUID, seriesInstanceUID, sopInstanceUID)); + } + else { + LOGGER.warn("Can't validate a token for switching KHEOPS album [{}]. The series [{}] won't be shared.", + kheopsAlbumsEntity.getId(), seriesInstanceUID); + } + } + } + + private boolean validateToken(List validMinScope, String urlAPI, String introspectToken) { + try { + JSONObject responseIntrospect = kheopsAPI.tokenIntrospect(urlAPI, introspectToken, introspectToken); + return validateIntrospectedToken(responseIntrospect, validMinScope); + } + catch (InterruptedException e) { + LOGGER.warn("Session interrupted", e); + Thread.currentThread().interrupt(); + } + catch (Exception e) { + LOGGER.error("Invalid token", e); + } + return false; + } + + public void applyAfterTransfer(KheopsAlbumsEntity kheopsAlbumsEntity, Attributes dcm) { + String sopInstanceUID = dcm.getString(Tag.AffectedSOPInstanceUID); + if (sopInstanceUID == null) { + throw new IllegalStateException("AffectedSOPInstanceUID not found"); + } + Long id = kheopsAlbumsEntity.getId(); + String authorizationSource = kheopsAlbumsEntity.getAuthorizationSource(); + String authorizationDestination = kheopsAlbumsEntity.getAuthorizationDestination(); + String urlAPI = kheopsAlbumsEntity.getUrlAPI(); + + ArrayList metadataToDo = (ArrayList) switchingAlbumToDo.get(id); + metadataToDo.forEach(metadataSwitching -> { + if (metadataSwitching.getSOPinstanceUID().equals(sopInstanceUID) && !metadataSwitching.isApplied()) { + int status = shareSerie(urlAPI, metadataSwitching.getStudyInstanceUID(), + metadataSwitching.getSeriesInstanceUID(), authorizationSource, authorizationDestination); + if (status >= 400 && status <= 599) { + LOGGER.warn("Can't share the serie [{}] for switching KHEOPS album [{}]. The response status is {}", + metadataSwitching.getSeriesInstanceUID(), id, status); + metadataSwitching.setApplied(false); + } + else { + metadataSwitching.setApplied(true); + } + } + }); + } + + private int shareSerie(String urlAPI, String studyInstanceUID, String seriesInstanceUID, String authorizationSource, + String authorizationDestination) { + try { + return kheopsAPI.shareSerie(studyInstanceUID, seriesInstanceUID, urlAPI, authorizationSource, + authorizationDestination); + } + catch (InterruptedException e) { + LOGGER.warn("Session interrupted", e); + Thread.currentThread().interrupt(); + } + catch (Exception e) { + LOGGER.error("Can't share the serie {} in the study {}", seriesInstanceUID, studyInstanceUID, e); + } + return -1; + } + } diff --git a/src/main/java/org/karnak/backend/service/profilepipe/AttributesByDefault.java b/src/main/java/org/karnak/backend/service/profilepipe/AttributesByDefault.java index eee0fdfee..5eb039360 100644 --- a/src/main/java/org/karnak/backend/service/profilepipe/AttributesByDefault.java +++ b/src/main/java/org/karnak/backend/service/profilepipe/AttributesByDefault.java @@ -28,63 +28,60 @@ public class AttributesByDefault { - private AttributesByDefault() {} + private AttributesByDefault() { + } - public static void setDeidentificationMethodCodeSequence( - Attributes dcm, ProjectEntity projectEntity) { - final ProfileEntity profileEntity = projectEntity.getProfileEntity(); - final List profileElementEntities = - profileEntity.getProfileElementEntities().stream() - .sorted(Comparator.comparing(ProfileElementEntity::getPosition)) - .collect(Collectors.toList()); + public static void setDeidentificationMethodCodeSequence(Attributes dcm, ProjectEntity projectEntity) { + final ProfileEntity profileEntity = projectEntity.getProfileEntity(); + final List profileElementEntities = profileEntity.getProfileElementEntities().stream() + .sorted(Comparator.comparing(ProfileElementEntity::getPosition)).collect(Collectors.toList()); - Sequence deidentificationMethodSequence = - dcm.newSequence(Tag.DeidentificationMethodCodeSequence, profileElementEntities.size()); - Set listCodeValue = new HashSet<>(); + Sequence deidentificationMethodSequence = dcm.newSequence(Tag.DeidentificationMethodCodeSequence, + profileElementEntities.size()); + Set listCodeValue = new HashSet<>(); - profileElementEntities.forEach( - profileElementEntity -> { - String codeValue = ProfileItemType.getCodeValue(profileElementEntity.getCodename()); - String codeMeaning = ProfileItemType.getCodeMeaning(profileElementEntity.getCodename()); - if (codeValue != null && listCodeValue.stream().noneMatch(s -> s.equals(codeValue))) { - Attributes attributes = new Attributes(dcm.bigEndian()); - attributes.setString(Tag.CodeValue, VR.SH, codeValue); - attributes.setString(Tag.CodingSchemeDesignator, VR.SH, "DCM"); - attributes.setString(Tag.CodeMeaning, VR.LO, codeMeaning); - deidentificationMethodSequence.add(attributes); - listCodeValue.add(codeValue); - } - }); - } + profileElementEntities.forEach(profileElementEntity -> { + String codeValue = ProfileItemType.getCodeValue(profileElementEntity.getCodename()); + String codeMeaning = ProfileItemType.getCodeMeaning(profileElementEntity.getCodename()); + if (codeValue != null && listCodeValue.stream().noneMatch(s -> s.equals(codeValue))) { + Attributes attributes = new Attributes(dcm.bigEndian()); + attributes.setString(Tag.CodeValue, VR.SH, codeValue); + attributes.setString(Tag.CodingSchemeDesignator, VR.SH, "DCM"); + attributes.setString(Tag.CodeMeaning, VR.LO, codeMeaning); + deidentificationMethodSequence.add(attributes); + listCodeValue.add(codeValue); + } + }); + } - public static void setPatientModule( - Attributes dcm, String newPatientID, String newPatientName, ProjectEntity projectEntity) { - dcm.setString(Tag.PatientID, VR.LO, newPatientID); - dcm.setString(Tag.PatientName, VR.PN, newPatientName); - dcm.setString(Tag.PatientIdentityRemoved, VR.CS, "YES"); - dcm.remove(Tag.DeidentificationMethod); - setDeidentificationMethodCodeSequence(dcm, projectEntity); - } + public static void setPatientModule(Attributes dcm, String newPatientID, String newPatientName, + ProjectEntity projectEntity) { + dcm.setString(Tag.PatientID, VR.LO, newPatientID); + dcm.setString(Tag.PatientName, VR.PN, newPatientName); + dcm.setString(Tag.PatientIdentityRemoved, VR.CS, "YES"); + dcm.remove(Tag.DeidentificationMethod); + setDeidentificationMethodCodeSequence(dcm, projectEntity); + } - public static void setSOPCommonModule(Attributes dcm) { - final LocalDateTime now = LocalDateTime.now(ZoneId.of("CET")); - dcm.setString(Tag.InstanceCreationDate, VR.DA, DateTimeUtils.formatDA(now)); - dcm.setString(Tag.InstanceCreationTime, VR.TM, DateTimeUtils.formatTM(now)); - } + public static void setSOPCommonModule(Attributes dcm) { + final LocalDateTime now = LocalDateTime.now(ZoneId.of("CET")); + dcm.setString(Tag.InstanceCreationDate, VR.DA, DateTimeUtils.formatDA(now)); + dcm.setString(Tag.InstanceCreationTime, VR.TM, DateTimeUtils.formatTM(now)); + } - public static void setClinicalTrialAttributes( - Attributes dcm, ProjectEntity projectEntity, String pseudonym) { - final ProfileEntity profileEntity = projectEntity.getProfileEntity(); + public static void setClinicalTrialAttributes(Attributes dcm, ProjectEntity projectEntity, String pseudonym) { + final ProfileEntity profileEntity = projectEntity.getProfileEntity(); + + // Clinical Trial Subject - Module + dcm.setString(Tag.ClinicalTrialSponsorName, VR.LO, projectEntity.getName()); + dcm.setString(Tag.ClinicalTrialProtocolID, VR.LO, profileEntity.getName()); + dcm.setNull(Tag.ClinicalTrialProtocolName, VR.LO); + dcm.setNull(Tag.ClinicalTrialSiteID, VR.LO); + dcm.setNull(Tag.ClinicalTrialSiteName, VR.LO); + dcm.setString(Tag.ClinicalTrialSubjectID, VR.LO, pseudonym); + dcm.remove(Tag.ClinicalTrialSubjectReadingID); + dcm.remove(Tag.ClinicalTrialProtocolEthicsCommitteeName); + dcm.remove(Tag.ClinicalTrialProtocolEthicsCommitteeApprovalNumber); + } - // Clinical Trial Subject - Module - dcm.setString(Tag.ClinicalTrialSponsorName, VR.LO, projectEntity.getName()); - dcm.setString(Tag.ClinicalTrialProtocolID, VR.LO, profileEntity.getName()); - dcm.setNull(Tag.ClinicalTrialProtocolName, VR.LO); - dcm.setNull(Tag.ClinicalTrialSiteID, VR.LO); - dcm.setNull(Tag.ClinicalTrialSiteName, VR.LO); - dcm.setString(Tag.ClinicalTrialSubjectID, VR.LO, pseudonym); - dcm.remove(Tag.ClinicalTrialSubjectReadingID); - dcm.remove(Tag.ClinicalTrialProtocolEthicsCommitteeName); - dcm.remove(Tag.ClinicalTrialProtocolEthicsCommitteeApprovalNumber); - } } diff --git a/src/main/java/org/karnak/backend/service/profilepipe/Profile.java b/src/main/java/org/karnak/backend/service/profilepipe/Profile.java index a22c9e7c7..6ed0e3041 100644 --- a/src/main/java/org/karnak/backend/service/profilepipe/Profile.java +++ b/src/main/java/org/karnak/backend/service/profilepipe/Profile.java @@ -59,315 +59,287 @@ public class Profile { - private static final Logger LOGGER = LoggerFactory.getLogger(Profile.class); - - private final List profiles; - private final Pseudonym pseudonym; - private final Map maskMap; - - public Profile(ProfileEntity profileEntity) { - this.maskMap = new HashMap<>(); - this.pseudonym = new Pseudonym(); - this.profiles = createProfilesList(profileEntity); - } - - public void addMaskMap(Map maskMap) { - this.maskMap.putAll(maskMap); - } - - public MaskArea getMask(String key) { - MaskArea mask = maskMap.get(key); - if (mask == null) { - mask = maskMap.get("*"); - } - return mask; - } - - public void addMask(String stationName, MaskArea maskArea) { - this.maskMap.put(stationName, maskArea); - } - - public static List getProfileItems(ProfileEntity profileEntity) { - final Set listProfileElementEntity = - profileEntity.getProfileElementEntities(); - List profileItems = new ArrayList<>(); - - for (ProfileElementEntity profileElementEntity : listProfileElementEntity) { - ProfileItemType t = ProfileItemType.getType(profileElementEntity.getCodename()); - if (t == null) { - LOGGER.error("Cannot find the profile codename: {}", profileElementEntity.getCodename()); - } else { - Object instanceProfileItem; - try { - instanceProfileItem = - t.getProfileClass() - .getConstructor(ProfileElementEntity.class) - .newInstance(profileElementEntity); - profileItems.add((ProfileItem) instanceProfileItem); - } catch (Exception e) { - LOGGER.error("Cannot build the profile: {}", t.getProfileClass().getName(), e); - } - } - } - profileItems.sort(Comparator.comparing(ProfileItem::getPosition)); - return profileItems; - } - - public List createProfilesList(final ProfileEntity profileEntity) { - if (profileEntity != null) { - List profileItems = getProfileItems(profileEntity); - profileEntity - .getMaskEntities() - .forEach( - m -> { - Color color = null; - if (StringUtil.hasText(m.getColor())) { - color = ActionTags.hexadecimal2Color(m.getColor()); - } - List shapeList = - m.getRectangles().stream().map(Shape.class::cast).collect(Collectors.toList()); - addMask(m.getStationName(), new MaskArea(shapeList, color)); - }); - return profileItems; - } - return Collections.emptyList(); - } - - public void applyAction( - Attributes dcm, - Attributes dcmCopy, - HMAC hmac, - ProfileItem profilePassedInSequence, - ActionItem actionPassedInSequence, - AttributeEditorContext context) { - for (int tag : dcm.tags()) { - VR vr = dcm.getVR(tag); - final ExprCondition exprCondition = new ExprCondition(dcmCopy); - - ActionItem currentAction = null; - ProfileItem currentProfile = null; - for (ProfileItem profileEntity : - profiles.stream() - .filter(p -> !(p instanceof CleanPixelData)) - .collect(Collectors.toList())) { - currentProfile = profileEntity; - - if (profileEntity.getCondition() == null - || profileEntity.getCodeName().equals(ProfileItemType.DEFACING.getClassAlias()) - || profileEntity - .getCodeName() - .equals(ProfileItemType.CLEAN_PIXEL_DATA.getClassAlias())) { - currentAction = profileEntity.getAction(dcm, dcmCopy, tag, hmac); - } else { - boolean conditionIsOk = - (Boolean) - ExpressionResult.get(profileEntity.getCondition(), exprCondition, Boolean.class); - if (conditionIsOk) { - currentAction = profileEntity.getAction(dcm, dcmCopy, tag, hmac); - } - } - - if (currentAction != null) { - break; - } - - if (profileEntity.equals(profilePassedInSequence)) { - currentAction = actionPassedInSequence; - break; - } - } - - if (!(currentAction instanceof Remove) - && !(currentAction instanceof ReplaceNull) - && vr == VR.SQ) { - final ProfileItem finalCurrentProfile = currentProfile; - final ActionItem finalCurrentAction = currentAction; - Sequence seq = dcm.getSequence(tag); - if (seq != null) { - for (Attributes d : seq) { - applyAction(d, dcmCopy, hmac, finalCurrentProfile, finalCurrentAction, context); - } - } - } else { - if (currentAction != null) { - try { - currentAction.execute(dcm, tag, hmac); - } catch (final Exception e) { - LOGGER.error( - "Cannot execute the currentAction {} for tag: {}", - currentAction, - TagUtils.toString(tag), - e); - } - } - } - } - } - - public void applyCleanPixelData( - Attributes dcmCopy, AttributeEditorContext context, ProfileEntity profileEntity) { - Object pix = dcmCopy.getValue(Tag.PixelData); - if ((pix instanceof BulkData || pix instanceof Fragments) - && !profileEntity.getMaskEntities().isEmpty() - && profiles.stream().anyMatch(p -> p instanceof CleanPixelData)) { - String sopClassUID = dcmCopy.getString(Tag.SOPClassUID); - if (!StringUtil.hasText(sopClassUID)) { - throw new IllegalStateException("DICOM Object does not contain sopClassUID"); - } - String scuPattern = sopClassUID + "."; - MaskArea mask = getMask(dcmCopy.getString(Tag.StationName)); - // A mask must be applied with all the US and Secondary Capture sopClassUID, and with - // BurnedInAnnotation - if (isCleanPixelAllowedDependingImageType(dcmCopy, sopClassUID, scuPattern) - && evaluateConditionCleanPixelData(dcmCopy)) { - context.setMaskArea(mask); - if (mask == null) { - throw new IllegalStateException( - "Clean pixel is not applied: mask not defined in station name"); - } - } else { - context.setMaskArea(null); - } - } - } - - /** - * Determine if the clean pixel should be applied depending on the image type - * - * @param dcmCopy Attributes - * @param sopClassUID SopClassUID - * @param scuPattern Pattern - * @return true if the clean pixel could be applied - */ - private boolean isCleanPixelAllowedDependingImageType( - Attributes dcmCopy, String sopClassUID, String scuPattern) { - // A mask must be applied with all the US and Secondary Capture sopClassUID, and with - // BurnedInAnnotation - return scuPattern.startsWith("1.2.840.10008.5.1.4.1.1.6.") - || scuPattern.startsWith("1.2.840.10008.5.1.4.1.1.7.") - || scuPattern.startsWith("1.2.840.10008.5.1.4.1.1.3.") - || sopClassUID.equals("1.2.840.10008.5.1.4.1.1.77.1.1") - || "YES".equalsIgnoreCase(dcmCopy.getString(Tag.BurnedInAnnotation)); - } - - /** - * Evaluate the condition on the profile Clean Pixel Data - * - * @param dcmCopy Context copy - * @return true if the condition match, false if there are some exclusions - */ - boolean evaluateConditionCleanPixelData(Attributes dcmCopy) { - boolean conditionCleanPixelData = true; - // Retrieve the profile item - ProfileItem profileItemCleanPixelData = - profiles.stream().filter(CleanPixelData.class::isInstance).findFirst().orElse(null); - if (profileItemCleanPixelData != null && profileItemCleanPixelData.getCondition() != null) { - // Evaluate the condition - ExprCondition exprCondition = new ExprCondition(dcmCopy); - conditionCleanPixelData = - (Boolean) - ExpressionResult.get( - profileItemCleanPixelData.getCondition(), exprCondition, Boolean.class); - } - return conditionCleanPixelData; - } - - public void applyDefacing(Attributes dcmCopy, AttributeEditorContext context) { - ProfileItem profileItemDefacing = - profiles.stream().filter(p -> p instanceof Defacing).findFirst().orElse(null); - if (profileItemDefacing != null) { - if (isCT(dcmCopy) && isAxial(dcmCopy)) { - if (profileItemDefacing.getCondition() == null) { - context.getProperties().setProperty(Defacer.APPLY_DEFACING, "true"); - } else { - ExprCondition exprCondition = new ExprCondition(dcmCopy); - boolean conditionIsOk = - (Boolean) - ExpressionResult.get( - profileItemDefacing.getCondition(), exprCondition, Boolean.class); - if (conditionIsOk) { - context.getProperties().setProperty(Defacer.APPLY_DEFACING, "true"); - } - } - } - } - } - - public void apply( - Attributes dcm, - DestinationEntity destinationEntity, - ProfileEntity profileEntity, - AttributeEditorContext context) { - final String SOPInstanceUID = dcm.getString(Tag.SOPInstanceUID); - final String SeriesInstanceUID = dcm.getString(Tag.SeriesInstanceUID); - final String IssuerOfPatientID = dcm.getString(Tag.IssuerOfPatientID); - final String PatientID = dcm.getString(Tag.PatientID); - final HMAC hmac = generateHMAC(destinationEntity, PatientID); - - MDC.put("SOPInstanceUID", SOPInstanceUID); - MDC.put("SeriesInstanceUID", SeriesInstanceUID); - MDC.put("issuerOfPatientID", IssuerOfPatientID); - MDC.put("PatientID", PatientID); - - String pseudonymValue = this.pseudonym.generatePseudonym(destinationEntity, dcm); - - String profilesCodeName = - profiles.stream().map(ProfileItem::getCodeName).collect(Collectors.joining("-")); - BigInteger patientValue = generatePatientID(pseudonymValue, hmac); - String newPatientID = patientValue.toString(16).toUpperCase(); - - Attributes dcmCopy = new Attributes(dcm); - - // Apply clean pixel data - applyCleanPixelData(dcmCopy, context, profileEntity); - - // Apply clean recognizable visual features option - applyDefacing(dcmCopy, context); - - applyAction(dcm, dcmCopy, hmac, null, null, context); - - // Set tags by default - AttributesByDefault.setPatientModule( - dcm, newPatientID, pseudonymValue, destinationEntity.getProjectEntity()); - AttributesByDefault.setSOPCommonModule(dcm); - AttributesByDefault.setClinicalTrialAttributes( - dcm, destinationEntity.getProjectEntity(), pseudonymValue); - - final Marker clincalMarker = MarkerFactory.getMarker("CLINICAL"); - MDC.put("DeidentifySOPInstanceUID", dcm.getString(Tag.SOPInstanceUID)); - MDC.put("DeidentifySeriesInstanceUID", dcm.getString(Tag.SeriesInstanceUID)); - MDC.put("ProjectName", destinationEntity.getProjectEntity().getName()); - MDC.put("ProfileName", profileEntity.getName()); - MDC.put("ProfileCodenames", profilesCodeName); - LOGGER.info(clincalMarker, ""); - MDC.clear(); - } - - private HMAC generateHMAC(DestinationEntity destinationEntity, String patientID) { - ProjectEntity projectEntity = destinationEntity.getProjectEntity(); - if (projectEntity == null) { - throw new IllegalStateException( - "Cannot build the HMAC a project is not associate at the destination"); - } - - SecretEntity secretEntity = projectEntity.retrieveActiveSecret(); - byte[] secret = secretEntity != null ? secretEntity.getKey() : null; - if (secret == null || secret.length != HMAC.KEY_BYTE_LENGTH) { - throw new IllegalStateException( - "Cannot build the HMAC no secret defined in the project associate at the destination"); - } - - if (patientID == null) { - throw new IllegalStateException("Cannot build the HMAC no PatientID given"); - } - - HashContext hashContext = new HashContext(secret, patientID); - return new HMAC(hashContext); - } - - public BigInteger generatePatientID(String pseudonym, HMAC hmac) { - byte[] bytes = new byte[16]; - System.arraycopy(hmac.byteHash(pseudonym), 0, bytes, 0, 16); - return new BigInteger(1, bytes); - } + private static final Logger LOGGER = LoggerFactory.getLogger(Profile.class); + + private final List profiles; + + private final Pseudonym pseudonym; + + private final Map maskMap; + + public Profile(ProfileEntity profileEntity) { + this.maskMap = new HashMap<>(); + this.pseudonym = new Pseudonym(); + this.profiles = createProfilesList(profileEntity); + } + + public void addMaskMap(Map maskMap) { + this.maskMap.putAll(maskMap); + } + + public MaskArea getMask(String key) { + MaskArea mask = maskMap.get(key); + if (mask == null) { + mask = maskMap.get("*"); + } + return mask; + } + + public void addMask(String stationName, MaskArea maskArea) { + this.maskMap.put(stationName, maskArea); + } + + public static List getProfileItems(ProfileEntity profileEntity) { + final Set listProfileElementEntity = profileEntity.getProfileElementEntities(); + List profileItems = new ArrayList<>(); + + for (ProfileElementEntity profileElementEntity : listProfileElementEntity) { + ProfileItemType t = ProfileItemType.getType(profileElementEntity.getCodename()); + if (t == null) { + LOGGER.error("Cannot find the profile codename: {}", profileElementEntity.getCodename()); + } + else { + Object instanceProfileItem; + try { + instanceProfileItem = t.getProfileClass().getConstructor(ProfileElementEntity.class) + .newInstance(profileElementEntity); + profileItems.add((ProfileItem) instanceProfileItem); + } + catch (Exception e) { + LOGGER.error("Cannot build the profile: {}", t.getProfileClass().getName(), e); + } + } + } + profileItems.sort(Comparator.comparing(ProfileItem::getPosition)); + return profileItems; + } + + public List createProfilesList(final ProfileEntity profileEntity) { + if (profileEntity != null) { + List profileItems = getProfileItems(profileEntity); + profileEntity.getMaskEntities().forEach(m -> { + Color color = null; + if (StringUtil.hasText(m.getColor())) { + color = ActionTags.hexadecimal2Color(m.getColor()); + } + List shapeList = m.getRectangles().stream().map(Shape.class::cast).collect(Collectors.toList()); + addMask(m.getStationName(), new MaskArea(shapeList, color)); + }); + return profileItems; + } + return Collections.emptyList(); + } + + public void applyAction(Attributes dcm, Attributes dcmCopy, HMAC hmac, ProfileItem profilePassedInSequence, + ActionItem actionPassedInSequence, AttributeEditorContext context) { + for (int tag : dcm.tags()) { + VR vr = dcm.getVR(tag); + final ExprCondition exprCondition = new ExprCondition(dcmCopy); + + ActionItem currentAction = null; + ProfileItem currentProfile = null; + for (ProfileItem profileEntity : profiles.stream().filter(p -> !(p instanceof CleanPixelData)) + .collect(Collectors.toList())) { + currentProfile = profileEntity; + + if (profileEntity.getCondition() == null + || profileEntity.getCodeName().equals(ProfileItemType.DEFACING.getClassAlias()) + || profileEntity.getCodeName().equals(ProfileItemType.CLEAN_PIXEL_DATA.getClassAlias())) { + currentAction = profileEntity.getAction(dcm, dcmCopy, tag, hmac); + } + else { + boolean conditionIsOk = (Boolean) ExpressionResult.get(profileEntity.getCondition(), exprCondition, + Boolean.class); + if (conditionIsOk) { + currentAction = profileEntity.getAction(dcm, dcmCopy, tag, hmac); + } + } + + if (currentAction != null) { + break; + } + + if (profileEntity.equals(profilePassedInSequence)) { + currentAction = actionPassedInSequence; + break; + } + } + + if (!(currentAction instanceof Remove) && !(currentAction instanceof ReplaceNull) && vr == VR.SQ) { + final ProfileItem finalCurrentProfile = currentProfile; + final ActionItem finalCurrentAction = currentAction; + Sequence seq = dcm.getSequence(tag); + if (seq != null) { + for (Attributes d : seq) { + applyAction(d, dcmCopy, hmac, finalCurrentProfile, finalCurrentAction, context); + } + } + } + else { + if (currentAction != null) { + try { + currentAction.execute(dcm, tag, hmac); + } + catch (final Exception e) { + LOGGER.error("Cannot execute the currentAction {} for tag: {}", currentAction, + TagUtils.toString(tag), e); + } + } + } + } + } + + public void applyCleanPixelData(Attributes dcmCopy, AttributeEditorContext context, ProfileEntity profileEntity) { + Object pix = dcmCopy.getValue(Tag.PixelData); + if ((pix instanceof BulkData || pix instanceof Fragments) && !profileEntity.getMaskEntities().isEmpty() + && profiles.stream().anyMatch(p -> p instanceof CleanPixelData)) { + String sopClassUID = dcmCopy.getString(Tag.SOPClassUID); + if (!StringUtil.hasText(sopClassUID)) { + throw new IllegalStateException("DICOM Object does not contain sopClassUID"); + } + String scuPattern = sopClassUID + "."; + MaskArea mask = getMask(dcmCopy.getString(Tag.StationName)); + // A mask must be applied with all the US and Secondary Capture sopClassUID, + // and with + // BurnedInAnnotation + if (isCleanPixelAllowedDependingImageType(dcmCopy, sopClassUID, scuPattern) + && evaluateConditionCleanPixelData(dcmCopy)) { + context.setMaskArea(mask); + if (mask == null) { + throw new IllegalStateException("Clean pixel is not applied: mask not defined in station name"); + } + } + else { + context.setMaskArea(null); + } + } + } + + /** + * Determine if the clean pixel should be applied depending on the image type + * @param dcmCopy Attributes + * @param sopClassUID SopClassUID + * @param scuPattern Pattern + * @return true if the clean pixel could be applied + */ + private boolean isCleanPixelAllowedDependingImageType(Attributes dcmCopy, String sopClassUID, String scuPattern) { + // A mask must be applied with all the US and Secondary Capture sopClassUID, and + // with + // BurnedInAnnotation + return scuPattern.startsWith("1.2.840.10008.5.1.4.1.1.6.") + || scuPattern.startsWith("1.2.840.10008.5.1.4.1.1.7.") + || scuPattern.startsWith("1.2.840.10008.5.1.4.1.1.3.") + || sopClassUID.equals("1.2.840.10008.5.1.4.1.1.77.1.1") + || "YES".equalsIgnoreCase(dcmCopy.getString(Tag.BurnedInAnnotation)); + } + + /** + * Evaluate the condition on the profile Clean Pixel Data + * @param dcmCopy Context copy + * @return true if the condition match, false if there are some exclusions + */ + boolean evaluateConditionCleanPixelData(Attributes dcmCopy) { + boolean conditionCleanPixelData = true; + // Retrieve the profile item + ProfileItem profileItemCleanPixelData = profiles.stream().filter(CleanPixelData.class::isInstance).findFirst() + .orElse(null); + if (profileItemCleanPixelData != null && profileItemCleanPixelData.getCondition() != null) { + // Evaluate the condition + ExprCondition exprCondition = new ExprCondition(dcmCopy); + conditionCleanPixelData = (Boolean) ExpressionResult.get(profileItemCleanPixelData.getCondition(), + exprCondition, Boolean.class); + } + return conditionCleanPixelData; + } + + public void applyDefacing(Attributes dcmCopy, AttributeEditorContext context) { + ProfileItem profileItemDefacing = profiles.stream().filter(p -> p instanceof Defacing).findFirst().orElse(null); + if (profileItemDefacing != null) { + if (isCT(dcmCopy) && isAxial(dcmCopy)) { + if (profileItemDefacing.getCondition() == null) { + context.getProperties().setProperty(Defacer.APPLY_DEFACING, "true"); + } + else { + ExprCondition exprCondition = new ExprCondition(dcmCopy); + boolean conditionIsOk = (Boolean) ExpressionResult.get(profileItemDefacing.getCondition(), + exprCondition, Boolean.class); + if (conditionIsOk) { + context.getProperties().setProperty(Defacer.APPLY_DEFACING, "true"); + } + } + } + } + } + + public void apply(Attributes dcm, DestinationEntity destinationEntity, ProfileEntity profileEntity, + AttributeEditorContext context) { + final String SOPInstanceUID = dcm.getString(Tag.SOPInstanceUID); + final String SeriesInstanceUID = dcm.getString(Tag.SeriesInstanceUID); + final String IssuerOfPatientID = dcm.getString(Tag.IssuerOfPatientID); + final String PatientID = dcm.getString(Tag.PatientID); + final HMAC hmac = generateHMAC(destinationEntity, PatientID); + + MDC.put("SOPInstanceUID", SOPInstanceUID); + MDC.put("SeriesInstanceUID", SeriesInstanceUID); + MDC.put("issuerOfPatientID", IssuerOfPatientID); + MDC.put("PatientID", PatientID); + + String pseudonymValue = this.pseudonym.generatePseudonym(destinationEntity, dcm); + + String profilesCodeName = profiles.stream().map(ProfileItem::getCodeName).collect(Collectors.joining("-")); + BigInteger patientValue = generatePatientID(pseudonymValue, hmac); + String newPatientID = patientValue.toString(16).toUpperCase(); + + Attributes dcmCopy = new Attributes(dcm); + + // Apply clean pixel data + applyCleanPixelData(dcmCopy, context, profileEntity); + + // Apply clean recognizable visual features option + applyDefacing(dcmCopy, context); + + applyAction(dcm, dcmCopy, hmac, null, null, context); + + // Set tags by default + AttributesByDefault.setPatientModule(dcm, newPatientID, pseudonymValue, destinationEntity.getProjectEntity()); + AttributesByDefault.setSOPCommonModule(dcm); + AttributesByDefault.setClinicalTrialAttributes(dcm, destinationEntity.getProjectEntity(), pseudonymValue); + + final Marker clincalMarker = MarkerFactory.getMarker("CLINICAL"); + MDC.put("DeidentifySOPInstanceUID", dcm.getString(Tag.SOPInstanceUID)); + MDC.put("DeidentifySeriesInstanceUID", dcm.getString(Tag.SeriesInstanceUID)); + MDC.put("ProjectName", destinationEntity.getProjectEntity().getName()); + MDC.put("ProfileName", profileEntity.getName()); + MDC.put("ProfileCodenames", profilesCodeName); + LOGGER.info(clincalMarker, ""); + MDC.clear(); + } + + private HMAC generateHMAC(DestinationEntity destinationEntity, String patientID) { + ProjectEntity projectEntity = destinationEntity.getProjectEntity(); + if (projectEntity == null) { + throw new IllegalStateException("Cannot build the HMAC a project is not associate at the destination"); + } + + SecretEntity secretEntity = projectEntity.retrieveActiveSecret(); + byte[] secret = secretEntity != null ? secretEntity.getKey() : null; + if (secret == null || secret.length != HMAC.KEY_BYTE_LENGTH) { + throw new IllegalStateException( + "Cannot build the HMAC no secret defined in the project associate at the destination"); + } + + if (patientID == null) { + throw new IllegalStateException("Cannot build the HMAC no PatientID given"); + } + + HashContext hashContext = new HashContext(secret, patientID); + return new HMAC(hashContext); + } + + public BigInteger generatePatientID(String pseudonym, HMAC hmac) { + byte[] bytes = new byte[16]; + System.arraycopy(hmac.byteHash(pseudonym), 0, bytes, 0, 16); + return new BigInteger(1, bytes); + } + } diff --git a/src/main/java/org/karnak/backend/service/profilepipe/ProfilePipeService.java b/src/main/java/org/karnak/backend/service/profilepipe/ProfilePipeService.java index 24638deb5..64f7efdf4 100644 --- a/src/main/java/org/karnak/backend/service/profilepipe/ProfilePipeService.java +++ b/src/main/java/org/karnak/backend/service/profilepipe/ProfilePipeService.java @@ -28,131 +28,101 @@ @Service public class ProfilePipeService { - // Repositories - private final ProfileRepo profileRepo; - - @Autowired - public ProfilePipeService(final ProfileRepo profileRepo) { - this.profileRepo = profileRepo; - } - - public List getAllProfiles() { - List list = new ArrayList<>(); - profileRepo - .findAll() // - .forEach(list::add); - return list; - } - - public ArrayList validateProfile(ProfilePipeBody profilePipeYml) { - ProfileEntity newProfileEntity = createNewProfile(profilePipeYml, false); - ArrayList profileErrors = new ArrayList<>(); - for (ProfileElementEntity profileElementEntity : newProfileEntity.getProfileElementEntities()) { - ProfileError profileError = new ProfileError(profileElementEntity); - profileErrors.add(profileError); - ProfileItemType t = ProfileItemType.getType(profileElementEntity.getCodename()); - if (t == null) { - profileError.setError( - "Cannot find the profile codename: " + profileElementEntity.getCodename()); - } else { - try { - t.getProfileClass() - .getConstructor(ProfileElementEntity.class) - .newInstance(profileElementEntity); - } catch (Exception e) { - profileError.setError(e.getCause().getMessage()); - continue; - } - } - } - return profileErrors; - } - - public ProfileEntity saveProfilePipe(ProfilePipeBody profilePipeYml, Boolean byDefault) { - ProfileEntity newProfileEntity = createNewProfile(profilePipeYml, byDefault); - return profileRepo.saveAndFlush(newProfileEntity); - } - - private ProfileEntity createNewProfile(ProfilePipeBody profilePipeYml, Boolean byDefault) { - final ProfileEntity newProfileEntity = - new ProfileEntity( - profilePipeYml.getName(), - profilePipeYml.getVersion(), - profilePipeYml.getMinimumKarnakVersion(), - null, - byDefault); - if (profilePipeYml.getMasks() != null) { - profilePipeYml - .getMasks() - .forEach( - m -> { - MaskEntity maskEntity = - new MaskEntity(m.getStationName(), m.getColor(), newProfileEntity); - m.getRectangles().forEach(maskEntity::addRectangle); - newProfileEntity.addMask(maskEntity); - }); - } - - AtomicInteger profilePosition = new AtomicInteger(0); - profilePipeYml - .getProfileElements() - .forEach( - profileBody -> { - ProfileElementEntity profileElementEntity = - new ProfileElementEntity( - profileBody.getName(), - profileBody.getCodename(), - profileBody.getCondition(), - profileBody.getAction(), - profileBody.getOption(), - profilePosition.get(), - newProfileEntity); - - if (profileBody.getArguments() != null) { - profileBody - .getArguments() - .forEach( - (key, value) -> { - final ArgumentEntity argumentEntity = - new ArgumentEntity(key, value, profileElementEntity); - profileElementEntity.addArgument(argumentEntity); - }); - } - - if (profileBody.getTags() != null) { - profileBody - .getTags() - .forEach( - tag -> { - final IncludedTagEntity includedTagEntityValue = - new IncludedTagEntity(tag, profileElementEntity); - profileElementEntity.addIncludedTag(includedTagEntityValue); - }); - } - - if (profileBody.getExcludedTags() != null) { - profileBody - .getExcludedTags() - .forEach( - excludedTag -> { - final ExcludedTagEntity excludedTagEntityValue = - new ExcludedTagEntity(excludedTag, profileElementEntity); - profileElementEntity.addExceptedtags(excludedTagEntityValue); - }); - } - - newProfileEntity.addProfilePipe(profileElementEntity); - profilePosition.getAndIncrement(); - }); - return newProfileEntity; - } - - public ProfileEntity updateProfile(ProfileEntity profileEntity) { - return profileRepo.saveAndFlush(profileEntity); - } - - public void deleteProfile(ProfileEntity profileEntity) { - profileRepo.deleteById(profileEntity.getId()); - profileRepo.flush(); - } + // Repositories + private final ProfileRepo profileRepo; + + @Autowired + public ProfilePipeService(final ProfileRepo profileRepo) { + this.profileRepo = profileRepo; + } + + public List getAllProfiles() { + List list = new ArrayList<>(); + profileRepo.findAll() // + .forEach(list::add); + return list; + } + + public ArrayList validateProfile(ProfilePipeBody profilePipeYml) { + ProfileEntity newProfileEntity = createNewProfile(profilePipeYml, false); + ArrayList profileErrors = new ArrayList<>(); + for (ProfileElementEntity profileElementEntity : newProfileEntity.getProfileElementEntities()) { + ProfileError profileError = new ProfileError(profileElementEntity); + profileErrors.add(profileError); + ProfileItemType t = ProfileItemType.getType(profileElementEntity.getCodename()); + if (t == null) { + profileError.setError("Cannot find the profile codename: " + profileElementEntity.getCodename()); + } + else { + try { + t.getProfileClass().getConstructor(ProfileElementEntity.class).newInstance(profileElementEntity); + } + catch (Exception e) { + profileError.setError(e.getCause().getMessage()); + continue; + } + } + } + return profileErrors; + } + + public ProfileEntity saveProfilePipe(ProfilePipeBody profilePipeYml, Boolean byDefault) { + ProfileEntity newProfileEntity = createNewProfile(profilePipeYml, byDefault); + return profileRepo.saveAndFlush(newProfileEntity); + } + + private ProfileEntity createNewProfile(ProfilePipeBody profilePipeYml, Boolean byDefault) { + final ProfileEntity newProfileEntity = new ProfileEntity(profilePipeYml.getName(), profilePipeYml.getVersion(), + profilePipeYml.getMinimumKarnakVersion(), null, byDefault); + if (profilePipeYml.getMasks() != null) { + profilePipeYml.getMasks().forEach(m -> { + MaskEntity maskEntity = new MaskEntity(m.getStationName(), m.getColor(), newProfileEntity); + m.getRectangles().forEach(maskEntity::addRectangle); + newProfileEntity.addMask(maskEntity); + }); + } + + AtomicInteger profilePosition = new AtomicInteger(0); + profilePipeYml.getProfileElements().forEach(profileBody -> { + ProfileElementEntity profileElementEntity = new ProfileElementEntity(profileBody.getName(), + profileBody.getCodename(), profileBody.getCondition(), profileBody.getAction(), + profileBody.getOption(), profilePosition.get(), newProfileEntity); + + if (profileBody.getArguments() != null) { + profileBody.getArguments().forEach((key, value) -> { + final ArgumentEntity argumentEntity = new ArgumentEntity(key, value, profileElementEntity); + profileElementEntity.addArgument(argumentEntity); + }); + } + + if (profileBody.getTags() != null) { + profileBody.getTags().forEach(tag -> { + final IncludedTagEntity includedTagEntityValue = new IncludedTagEntity(tag, profileElementEntity); + profileElementEntity.addIncludedTag(includedTagEntityValue); + }); + } + + if (profileBody.getExcludedTags() != null) { + profileBody.getExcludedTags().forEach(excludedTag -> { + final ExcludedTagEntity excludedTagEntityValue = new ExcludedTagEntity(excludedTag, + profileElementEntity); + profileElementEntity.addExceptedtags(excludedTagEntityValue); + }); + } + + newProfileEntity.addProfilePipe(profileElementEntity); + profilePosition.getAndIncrement(); + }); + return newProfileEntity; + } + + public ProfileEntity updateProfile(ProfileEntity profileEntity) { + return profileRepo.saveAndFlush(profileEntity); + } + + public void deleteProfile(ProfileEntity profileEntity) { + profileRepo.deleteById(profileEntity.getId()); + profileRepo.flush(); + } + } diff --git a/src/main/java/org/karnak/backend/service/profilepipe/Pseudonym.java b/src/main/java/org/karnak/backend/service/profilepipe/Pseudonym.java index ac2ca944e..392019163 100644 --- a/src/main/java/org/karnak/backend/service/profilepipe/Pseudonym.java +++ b/src/main/java/org/karnak/backend/service/profilepipe/Pseudonym.java @@ -25,128 +25,120 @@ public class Pseudonym { - private static final Logger LOGGER = LoggerFactory.getLogger(Pseudonym.class); - - private final PatientClient externalIdCache; - private final PatientClient mainzellisteCache; - - public Pseudonym() { - this.externalIdCache = AppConfig.getInstance().getExternalIDCache(); - this.mainzellisteCache = AppConfig.getInstance().getMainzellisteCache(); - } - - public String generatePseudonym(DestinationEntity destinationEntity, Attributes dcm) { - - PatientMetadata patientMetadata; - if (destinationEntity.getIssuerByDefault() == null - || destinationEntity.getIssuerByDefault().equals("")) { - patientMetadata = new PatientMetadata(dcm); - } else { - patientMetadata = new PatientMetadata(dcm, destinationEntity.getIssuerByDefault()); - } - - if (destinationEntity.getPseudonymType().equals(PseudonymType.CACHE_EXTID)) { - return getCacheExtid(patientMetadata, destinationEntity.getProjectEntity().getId()); - } - - if (destinationEntity.getPseudonymType().equals(PseudonymType.EXTID_IN_TAG)) { - return getPseudonymInDicom(dcm, destinationEntity, patientMetadata); - } - - final String cachedMainezllistePseudonym = - PatientClientUtil.getPseudonym(patientMetadata, mainzellisteCache); - if (cachedMainezllistePseudonym != null) { - cachingMainzellistePseudonym(cachedMainezllistePseudonym, patientMetadata); - return cachedMainezllistePseudonym; - } - - if (destinationEntity - .getPseudonymType() - .equals(PseudonymType.MAINZELLISTE_PID)) { // MAINZELLISTE - return getMainzellistePID(patientMetadata); - } - - if (destinationEntity.getPseudonymType().equals(PseudonymType.MAINZELLISTE_EXTID)) { - return getMainzellisteExtID(patientMetadata); - } - - return null; - } - - private String getPseudonymInDicom( - Attributes dcm, DestinationEntity destinationEntity, PatientMetadata patientMetadata) { - final String cleanTag = destinationEntity.getTag().replaceAll("[(),]", "").toUpperCase(); - final String tagValue = dcm.getString(TagUtils.intFromHexString(cleanTag)); - String pseudonymExtidInTag = null; - - if (tagValue != null - && destinationEntity.getDelimiter() != null - && destinationEntity.getPosition() != null - && !destinationEntity.getDelimiter().equals("")) { - String delimiterSpec = - SpecialCharacter.escapeSpecialRegexChars(destinationEntity.getDelimiter()); - try { - pseudonymExtidInTag = tagValue.split(delimiterSpec)[destinationEntity.getPosition()]; - } catch (ArrayIndexOutOfBoundsException e) { - LOGGER.error("Can not split the external pseudonym", e); - } - } else { - pseudonymExtidInTag = tagValue; - } - - if (pseudonymExtidInTag == null) { - throw new IllegalStateException("Cannot get a pseudonym in a DICOM tag"); - } else { - if (destinationEntity.getSavePseudonym().booleanValue()) { - final PseudonymApi pseudonymApi = new PseudonymApi(); - pseudonymApi.addExtID(patientMetadata.generateMainzellisteFields(), pseudonymExtidInTag); - } - } - return pseudonymExtidInTag; - } - - public String getCacheExtid(PatientMetadata patientMetadata, Long projectID) { - final String pseudonymCacheExtID = - PatientClientUtil.getPseudonym(patientMetadata, externalIdCache, projectID); - if (pseudonymCacheExtID == null) { - throw new IllegalStateException("Cannot get an external pseudonym in cache"); - } - return pseudonymCacheExtID; - } - - public String getMainzellistePID(PatientMetadata patientMetadata) { - final PseudonymApi pseudonymApi = new PseudonymApi(); - final String pseudonymMainzellistePID = - pseudonymApi.generatePID(patientMetadata.generateMainzellisteFields()); - if (pseudonymMainzellistePID == null) { - throw new IllegalStateException("Cannot get pseudonym of type pid in Mainzelliste API"); - } - cachingMainzellistePseudonym(pseudonymMainzellistePID, patientMetadata); - return pseudonymMainzellistePID; - } - - public String getMainzellisteExtID(PatientMetadata patientMetadata) { - final PseudonymApi pseudonymApi = new PseudonymApi(); - final String pseudonymMainzellisteExtID = - pseudonymApi.getExistingExtID(patientMetadata.generateMainzellisteFields()); - if (pseudonymMainzellisteExtID == null) { - throw new IllegalStateException("Cannot get pseudonym of type extid in Mainzelliste API"); - } - cachingMainzellistePseudonym(pseudonymMainzellisteExtID, patientMetadata); - return pseudonymMainzellisteExtID; - } - - private void cachingMainzellistePseudonym(String pseudonym, PatientMetadata patientMetadata) { - final MainzellistePatient mainzellistePatient = - new MainzellistePatient( - pseudonym, - patientMetadata.getPatientID(), - patientMetadata.getPatientFirstName(), - patientMetadata.getPatientLastName(), - patientMetadata.getLocalDatePatientBirthDate(), - patientMetadata.getPatientSex(), - patientMetadata.getIssuerOfPatientID()); - String cacheKey = PatientClientUtil.generateKey(patientMetadata); - mainzellisteCache.put(cacheKey, mainzellistePatient); - } + private static final Logger LOGGER = LoggerFactory.getLogger(Pseudonym.class); + + private final PatientClient externalIdCache; + + private final PatientClient mainzellisteCache; + + public Pseudonym() { + this.externalIdCache = AppConfig.getInstance().getExternalIDCache(); + this.mainzellisteCache = AppConfig.getInstance().getMainzellisteCache(); + } + + public String generatePseudonym(DestinationEntity destinationEntity, Attributes dcm) { + + PatientMetadata patientMetadata; + if (destinationEntity.getIssuerByDefault() == null || destinationEntity.getIssuerByDefault().equals("")) { + patientMetadata = new PatientMetadata(dcm); + } + else { + patientMetadata = new PatientMetadata(dcm, destinationEntity.getIssuerByDefault()); + } + + if (destinationEntity.getPseudonymType().equals(PseudonymType.CACHE_EXTID)) { + return getCacheExtid(patientMetadata, destinationEntity.getProjectEntity().getId()); + } + + if (destinationEntity.getPseudonymType().equals(PseudonymType.EXTID_IN_TAG)) { + return getPseudonymInDicom(dcm, destinationEntity, patientMetadata); + } + + final String cachedMainezllistePseudonym = PatientClientUtil.getPseudonym(patientMetadata, mainzellisteCache); + if (cachedMainezllistePseudonym != null) { + cachingMainzellistePseudonym(cachedMainezllistePseudonym, patientMetadata); + return cachedMainezllistePseudonym; + } + + if (destinationEntity.getPseudonymType().equals(PseudonymType.MAINZELLISTE_PID)) { // MAINZELLISTE + return getMainzellistePID(patientMetadata); + } + + if (destinationEntity.getPseudonymType().equals(PseudonymType.MAINZELLISTE_EXTID)) { + return getMainzellisteExtID(patientMetadata); + } + + return null; + } + + private String getPseudonymInDicom(Attributes dcm, DestinationEntity destinationEntity, + PatientMetadata patientMetadata) { + final String cleanTag = destinationEntity.getTag().replaceAll("[(),]", "").toUpperCase(); + final String tagValue = dcm.getString(TagUtils.intFromHexString(cleanTag)); + String pseudonymExtidInTag = null; + + if (tagValue != null && destinationEntity.getDelimiter() != null && destinationEntity.getPosition() != null + && !destinationEntity.getDelimiter().equals("")) { + String delimiterSpec = SpecialCharacter.escapeSpecialRegexChars(destinationEntity.getDelimiter()); + try { + pseudonymExtidInTag = tagValue.split(delimiterSpec)[destinationEntity.getPosition()]; + } + catch (ArrayIndexOutOfBoundsException e) { + LOGGER.error("Can not split the external pseudonym", e); + } + } + else { + pseudonymExtidInTag = tagValue; + } + + if (pseudonymExtidInTag == null) { + throw new IllegalStateException("Cannot get a pseudonym in a DICOM tag"); + } + else { + if (destinationEntity.getSavePseudonym().booleanValue()) { + final PseudonymApi pseudonymApi = new PseudonymApi(); + pseudonymApi.addExtID(patientMetadata.generateMainzellisteFields(), pseudonymExtidInTag); + } + } + return pseudonymExtidInTag; + } + + public String getCacheExtid(PatientMetadata patientMetadata, Long projectID) { + final String pseudonymCacheExtID = PatientClientUtil.getPseudonym(patientMetadata, externalIdCache, projectID); + if (pseudonymCacheExtID == null) { + throw new IllegalStateException("Cannot get an external pseudonym in cache"); + } + return pseudonymCacheExtID; + } + + public String getMainzellistePID(PatientMetadata patientMetadata) { + final PseudonymApi pseudonymApi = new PseudonymApi(); + final String pseudonymMainzellistePID = pseudonymApi.generatePID(patientMetadata.generateMainzellisteFields()); + if (pseudonymMainzellistePID == null) { + throw new IllegalStateException("Cannot get pseudonym of type pid in Mainzelliste API"); + } + cachingMainzellistePseudonym(pseudonymMainzellistePID, patientMetadata); + return pseudonymMainzellistePID; + } + + public String getMainzellisteExtID(PatientMetadata patientMetadata) { + final PseudonymApi pseudonymApi = new PseudonymApi(); + final String pseudonymMainzellisteExtID = pseudonymApi + .getExistingExtID(patientMetadata.generateMainzellisteFields()); + if (pseudonymMainzellisteExtID == null) { + throw new IllegalStateException("Cannot get pseudonym of type extid in Mainzelliste API"); + } + cachingMainzellistePseudonym(pseudonymMainzellisteExtID, patientMetadata); + return pseudonymMainzellisteExtID; + } + + private void cachingMainzellistePseudonym(String pseudonym, PatientMetadata patientMetadata) { + final MainzellistePatient mainzellistePatient = new MainzellistePatient(pseudonym, + patientMetadata.getPatientID(), patientMetadata.getPatientFirstName(), + patientMetadata.getPatientLastName(), patientMetadata.getLocalDatePatientBirthDate(), + patientMetadata.getPatientSex(), patientMetadata.getIssuerOfPatientID()); + String cacheKey = PatientClientUtil.generateKey(patientMetadata); + mainzellisteCache.put(cacheKey, mainzellistePatient); + } + } diff --git a/src/main/java/org/karnak/backend/service/thread/DicomEchoThread.java b/src/main/java/org/karnak/backend/service/thread/DicomEchoThread.java index 789b54152..93a1873ba 100644 --- a/src/main/java/org/karnak/backend/service/thread/DicomEchoThread.java +++ b/src/main/java/org/karnak/backend/service/thread/DicomEchoThread.java @@ -16,33 +16,33 @@ public class DicomEchoThread implements Callable { - private final ConfigNode node; - - public DicomEchoThread(ConfigNode node) { - this.node = node; - } - - @Override - public String call() throws Exception { - StringBuilder result = new StringBuilder(); - - result.append("

"); - DicomNode dcmNode = node.getCalledNode(); - result.append("

DICOM Echo: "); - result.append(node.toString()); - result.append("
"); - result.append(dcmNode.toString()); - result.append("
"); - result.append(""); - boolean success = Util.getEchoResponse(result, "PACSMONITOR", dcmNode, true, "HTML", 3000); - if (!success) { - Util.getNetworkResponse( - result, dcmNode.getAet(), dcmNode.getHostname(), dcmNode.getPort(), true); - } - result.append(""); - result.append("

"); - result.append("
"); - - return result.toString(); - } + private final ConfigNode node; + + public DicomEchoThread(ConfigNode node) { + this.node = node; + } + + @Override + public String call() throws Exception { + StringBuilder result = new StringBuilder(); + + result.append("

"); + DicomNode dcmNode = node.getCalledNode(); + result.append("

DICOM Echo: "); + result.append(node); + result.append("
"); + result.append(dcmNode.toString()); + result.append("
"); + result.append(""); + boolean success = Util.getEchoResponse(result, "PACSMONITOR", dcmNode, true, "HTML", 3000); + if (!success) { + Util.getNetworkResponse(result, dcmNode.getAet(), dcmNode.getHostname(), dcmNode.getPort(), true); + } + result.append(""); + result.append("

"); + result.append("
"); + + return result.toString(); + } + } diff --git a/src/main/java/org/karnak/backend/service/thread/WadoResponse.java b/src/main/java/org/karnak/backend/service/thread/WadoResponse.java index 893d77bcb..1a459762a 100644 --- a/src/main/java/org/karnak/backend/service/thread/WadoResponse.java +++ b/src/main/java/org/karnak/backend/service/thread/WadoResponse.java @@ -15,24 +15,25 @@ public class WadoResponse implements Callable { - private final WadoNode node; - - public WadoResponse(WadoNode node) { - this.node = node; - } - - @Override - public String call() throws Exception { - StringBuilder result = new StringBuilder(); - - result.append("
WADO HTTP-GET: "); - result.append(node.toString()); - result.append("
"); - result.append(""); - Util.getWadoResponse(result, node, true, "HTML", 10000); - result.append(""); - result.append("
"); - - return result.toString(); - } + private final WadoNode node; + + public WadoResponse(WadoNode node) { + this.node = node; + } + + @Override + public String call() throws Exception { + StringBuilder result = new StringBuilder(); + + result.append("
WADO HTTP-GET: "); + result.append(node.toString()); + result.append("
"); + result.append(""); + Util.getWadoResponse(result, node, true, "HTML", 10000); + result.append(""); + result.append("
"); + + return result.toString(); + } + } diff --git a/src/main/java/org/karnak/backend/util/Counter.java b/src/main/java/org/karnak/backend/util/Counter.java index 5972fa6b1..f8901f31f 100644 --- a/src/main/java/org/karnak/backend/util/Counter.java +++ b/src/main/java/org/karnak/backend/util/Counter.java @@ -13,22 +13,24 @@ public class Counter { - private final AtomicInteger count = new AtomicInteger(0); - private final int interval; + private final AtomicInteger count = new AtomicInteger(0); - public Counter(int interval) { - this.interval = interval; - } + private final int interval; - public int getCount() { - return count.get(); - } + public Counter(int interval) { + this.interval = interval; + } - public void resetCount() { - this.count.set(0); - } + public int getCount() { + return count.get(); + } + + public void resetCount() { + this.count.set(0); + } + + public int increment() { + return this.count.addAndGet(interval); + } - public int increment() { - return this.count.addAndGet(interval); - } } diff --git a/src/main/java/org/karnak/backend/util/DateFormat.java b/src/main/java/org/karnak/backend/util/DateFormat.java index 5438d5fd0..e71584962 100644 --- a/src/main/java/org/karnak/backend/util/DateFormat.java +++ b/src/main/java/org/karnak/backend/util/DateFormat.java @@ -27,134 +27,126 @@ import org.slf4j.LoggerFactory; public class DateFormat { - private static final Logger LOGGER = LoggerFactory.getLogger(DateFormat.class); - - // Date formats - public static final String FORMAT_DDMMYYYY_SLASH = "dd/MM/yyyy"; - public static final String FORMAT_DDMMYYYY_SLASH_HHMMSS_2POINTS = "dd/MM/yyyy HH:mm:ss"; - public static final String FORMAT_DDMMYYYY_SLASH_HHMMSS_2POINTS_SSS_POINT = - "dd/MM/yyyy HH:mm:ss.SSS"; - public static final String FORMAT_DDMMYYYY_SLASH_HHMMSS_2POINTS_SSSSSS_POINT = - "dd/MM/yyyy HH:mm:ss.SSSSSS"; - - /** - * Build DateTimeFormatter - * - * @param format Date format - * @return DateTimeFormatter - */ - public static DateTimeFormatter dateTimeFormatter(final String format) { - return new DateTimeFormatterBuilder() - .parseCaseInsensitive() - .appendPattern(format) - .toFormatter(Locale.ENGLISH); - } - - /** - * Format a LocalDate to a specifig - * - * @param date Date to format - * @param format Format to apply - * @return Formatted date String - */ - public static String format(final LocalDate date, final String format) { - return date == null ? null : date.format(dateTimeFormatter(format)); - } - - /** - * Format a LocalDateTime to a specific format - * - * @param dateTime Date to format - * @param format Format to apply - * @return Formatted date String - */ - public static String format(final LocalDateTime dateTime, final String format) { - return dateTime == null ? null : dateTime.format(dateTimeFormatter(format)); - } - - public static String formatDA(String date, String option) { - LocalDate localDate = DateTimeUtils.parseDA(date); - switch (option) { - case "day": - localDate = localDate.minusDays(localDate.getDayOfMonth() - 1L); - break; - case "month_day": - localDate = localDate.minusDays(localDate.getDayOfMonth() - 1L); - localDate = localDate.minusMonths(localDate.getMonthValue() - 1L); - } - - return localDate.format(DateTimeFormatter.ofPattern("yyyyMMdd")); - } - - public static String formatDT(String dateTime, String option) { - - Temporal localDateTime = DateTimeUtils.parseDT(dateTime); - - switch (option) { - case "day": - localDateTime = - localDateTime.minus(localDateTime.get(ChronoField.DAY_OF_MONTH) - 1L, ChronoUnit.DAYS); - break; - case "month_day": - localDateTime = - localDateTime.minus(localDateTime.get(ChronoField.DAY_OF_MONTH) - 1L, ChronoUnit.DAYS); - localDateTime = - localDateTime.minus( - localDateTime.get(ChronoField.MONTH_OF_YEAR) - 1L, ChronoUnit.MONTHS); - } - - return DateTimeUtils.formatDT(localDateTime); - } - - public static String format(Attributes dcm, int tag, List argumentEntities) - throws DateTimeException { - try { - verifyPatternArguments(argumentEntities); - } catch (IllegalArgumentException e) { - throw e; - } - - String dcmElValue = dcm.getString(tag); - String format = ""; - - for (ArgumentEntity argumentEntity : argumentEntities) { - final String key = argumentEntity.getKey(); - final String value = argumentEntity.getValue(); - - try { - if (key.equals("remove")) { - format = value; - } - } catch (Exception e) { - LOGGER.error("args {} is not correct", value, e); - } - } - if (dcmElValue != null) { - return switch (dcm.getVR(tag)) { - case DA -> formatDA(dcmElValue, format); - case DT -> formatDT(dcmElValue, format); - default -> null; - }; - } else { - return null; - } - } - - public static void verifyPatternArguments(List argumentEntities) - throws IllegalArgumentException { - List listValue = new ArrayList<>(); - listValue.add("day"); - listValue.add("month_day"); - - if (argumentEntities.stream() - .noneMatch( - argument -> - argument.getKey().equals("remove") && listValue.contains(argument.getValue()))) { - IllegalArgumentException missingParameters = - new IllegalArgumentException( - "Cannot build the option date_format, arguments are not correct"); - LOGGER.error("Missing argument, the class need pattern as parameters", missingParameters); - throw missingParameters; - } - } + + private static final Logger LOGGER = LoggerFactory.getLogger(DateFormat.class); + + // Date formats + public static final String FORMAT_DDMMYYYY_SLASH = "dd/MM/yyyy"; + + public static final String FORMAT_DDMMYYYY_SLASH_HHMMSS_2POINTS = "dd/MM/yyyy HH:mm:ss"; + + public static final String FORMAT_DDMMYYYY_SLASH_HHMMSS_2POINTS_SSS_POINT = "dd/MM/yyyy HH:mm:ss.SSS"; + + public static final String FORMAT_DDMMYYYY_SLASH_HHMMSS_2POINTS_SSSSSS_POINT = "dd/MM/yyyy HH:mm:ss.SSSSSS"; + + /** + * Build DateTimeFormatter + * @param format Date format + * @return DateTimeFormatter + */ + public static DateTimeFormatter dateTimeFormatter(final String format) { + return new DateTimeFormatterBuilder().parseCaseInsensitive().appendPattern(format).toFormatter(Locale.ENGLISH); + } + + /** + * Format a LocalDate to a specifig + * @param date Date to format + * @param format Format to apply + * @return Formatted date String + */ + public static String format(final LocalDate date, final String format) { + return date == null ? null : date.format(dateTimeFormatter(format)); + } + + /** + * Format a LocalDateTime to a specific format + * @param dateTime Date to format + * @param format Format to apply + * @return Formatted date String + */ + public static String format(final LocalDateTime dateTime, final String format) { + return dateTime == null ? null : dateTime.format(dateTimeFormatter(format)); + } + + public static String formatDA(String date, String option) { + LocalDate localDate = DateTimeUtils.parseDA(date); + switch (option) { + case "day": + localDate = localDate.minusDays(localDate.getDayOfMonth() - 1L); + break; + case "month_day": + localDate = localDate.minusDays(localDate.getDayOfMonth() - 1L); + localDate = localDate.minusMonths(localDate.getMonthValue() - 1L); + } + + return localDate.format(DateTimeFormatter.ofPattern("yyyyMMdd")); + } + + public static String formatDT(String dateTime, String option) { + + Temporal localDateTime = DateTimeUtils.parseDT(dateTime); + + switch (option) { + case "day": + localDateTime = localDateTime.minus(localDateTime.get(ChronoField.DAY_OF_MONTH) - 1L, ChronoUnit.DAYS); + break; + case "month_day": + localDateTime = localDateTime.minus(localDateTime.get(ChronoField.DAY_OF_MONTH) - 1L, ChronoUnit.DAYS); + localDateTime = localDateTime.minus(localDateTime.get(ChronoField.MONTH_OF_YEAR) - 1L, ChronoUnit.MONTHS); + } + + return DateTimeUtils.formatDT(localDateTime); + } + + public static String format(Attributes dcm, int tag, List argumentEntities) + throws DateTimeException { + try { + verifyPatternArguments(argumentEntities); + } + catch (IllegalArgumentException e) { + throw e; + } + + String dcmElValue = dcm.getString(tag); + String format = ""; + + for (ArgumentEntity argumentEntity : argumentEntities) { + final String key = argumentEntity.getKey(); + final String value = argumentEntity.getValue(); + + try { + if (key.equals("remove")) { + format = value; + } + } + catch (Exception e) { + LOGGER.error("args {} is not correct", value, e); + } + } + if (dcmElValue != null) { + return switch (dcm.getVR(tag)) { + case DA -> formatDA(dcmElValue, format); + case DT -> formatDT(dcmElValue, format); + default -> null; + }; + } + else { + return null; + } + } + + public static void verifyPatternArguments(List argumentEntities) throws IllegalArgumentException { + List listValue = new ArrayList<>(); + listValue.add("day"); + listValue.add("month_day"); + + if (argumentEntities.stream() + .noneMatch(argument -> argument.getKey().equals("remove") && listValue.contains(argument.getValue()))) { + IllegalArgumentException missingParameters = new IllegalArgumentException( + "Cannot build the option date_format, arguments are not correct"); + LOGGER.error("Missing argument, the class need pattern as parameters", missingParameters); + throw missingParameters; + } + } + } diff --git a/src/main/java/org/karnak/backend/util/DicomNodeUtil.java b/src/main/java/org/karnak/backend/util/DicomNodeUtil.java index 19953932f..f0269f2c2 100644 --- a/src/main/java/org/karnak/backend/util/DicomNodeUtil.java +++ b/src/main/java/org/karnak/backend/util/DicomNodeUtil.java @@ -16,21 +16,19 @@ public class DicomNodeUtil { - public static List getAllDicomNodeTypesDefinedLocally() { - List dicomNodeTypes = new ArrayList<>(); + public static List getAllDicomNodeTypesDefinedLocally() { + List dicomNodeTypes = new ArrayList<>(); - dicomNodeTypes.add( - Util.readnodes( - DicomNodeUtil.class.getResource("/config/workstations-nodes.csv"), "Workstations")); - dicomNodeTypes.add( - Util.readnodes( - DicomNodeUtil.class.getResource("/config/pacs-nodes-web.csv"), "PACS Public WEB")); + dicomNodeTypes + .add(Util.readnodes(DicomNodeUtil.class.getResource("/config/workstations-nodes.csv"), "Workstations")); + dicomNodeTypes + .add(Util.readnodes(DicomNodeUtil.class.getResource("/config/pacs-nodes-web.csv"), "PACS Public WEB")); - return dicomNodeTypes; - } + return dicomNodeTypes; + } + + public static DicomNodeList getAllWorkListNodesDefinedLocally() { + return Util.readnodes(DicomNodeUtil.class.getResource("/config/worklist-nodes.csv"), "Worklists"); + } - public static DicomNodeList getAllWorkListNodesDefinedLocally() { - return Util.readnodes( - DicomNodeUtil.class.getResource("/config/worklist-nodes.csv"), "Worklists"); - } } diff --git a/src/main/java/org/karnak/backend/util/DicomObjectTools.java b/src/main/java/org/karnak/backend/util/DicomObjectTools.java index b5b444cf0..08bb7f7df 100644 --- a/src/main/java/org/karnak/backend/util/DicomObjectTools.java +++ b/src/main/java/org/karnak/backend/util/DicomObjectTools.java @@ -21,110 +21,114 @@ public class DicomObjectTools { - public static boolean dicomObjectEquals(Attributes o1, Attributes o2) { - return Objects.equals(o1, o2); - } - - public static boolean containsTagFromPath(String path, Attributes dcm) { - if (!StringUtil.hasText(path)) { - throw new IllegalArgumentException("path cannot be empty!"); - } - - List tags = toTags(StringUtils.split(path, '.')); - int size = tags.size(); - if (size == 1) { - return dcm.contains(tags.get(0)); - } else if (size > 1) { - - } - - return false; - } - - public static List toTags(String[] tagOrKeywords) { - List tags = new ArrayList<>(tagOrKeywords.length); - for (int i = 0; i < tagOrKeywords.length; i++) { - tags.add(toTag(tagOrKeywords[i])); - } - return tags; - } - - public static int toTag(String tagOrKeyword) { - try { - return Integer.parseInt(tagOrKeyword, 16); - } catch (IllegalArgumentException e) { - int tag = ElementDictionary.tagForKeyword(tagOrKeyword, null); - if (tag == -1) { - throw new IllegalArgumentException(tagOrKeyword); - } - return tag; - } - } - - public static boolean containsTagInPath(List path, Attributes dcm) { - int size = path.size(); - if (size == 1) { - return dcm.contains(path.get(0)); - } - - List list = new ArrayList<>(); - - for (int i = 0; i < size; i++) { - int tag = path.get(i); - if (i == size - 1) { - for (Attributes item : list) { - if (item.contains(tag)) { - return true; - } - } - return false; - } - - if (list.isEmpty()) { - list = dcm.getSequence(tag); - } else { - list = getChildSequences(list, tag); - } - - if (list == null || list.isEmpty()) { - return false; - } - } - - return false; - } - - private static List getChildSequences(List seq, int seqTag) { - if (seq != null) { - List items = new ArrayList<>(); - for (Attributes item : seq) { - Sequence childSeq = item.getSequence(seqTag); - if (childSeq != null) { - items.addAll(childSeq); - } - } - return items; - } - return null; - } - - public static boolean containsTagInAllAttributes(int tag, Attributes dcm) { - if (dcm.contains(tag)) { - return true; - } - for (int t : dcm.tags()) { - if (dcm.getVR(t) == VR.SQ) { - Sequence seq = dcm.getSequence(t); - if (seq != null) { - for (Attributes item : seq) { - boolean result = containsTagInAllAttributes(tag, item); - if (result) { - return true; - } - } - } - } - } - return false; - } + public static boolean dicomObjectEquals(Attributes o1, Attributes o2) { + return Objects.equals(o1, o2); + } + + public static boolean containsTagFromPath(String path, Attributes dcm) { + if (!StringUtil.hasText(path)) { + throw new IllegalArgumentException("path cannot be empty!"); + } + + List tags = toTags(StringUtils.split(path, '.')); + int size = tags.size(); + if (size == 1) { + return dcm.contains(tags.get(0)); + } + else if (size > 1) { + + } + + return false; + } + + public static List toTags(String[] tagOrKeywords) { + List tags = new ArrayList<>(tagOrKeywords.length); + for (int i = 0; i < tagOrKeywords.length; i++) { + tags.add(toTag(tagOrKeywords[i])); + } + return tags; + } + + public static int toTag(String tagOrKeyword) { + try { + return Integer.parseInt(tagOrKeyword, 16); + } + catch (IllegalArgumentException e) { + int tag = ElementDictionary.tagForKeyword(tagOrKeyword, null); + if (tag == -1) { + throw new IllegalArgumentException(tagOrKeyword); + } + return tag; + } + } + + public static boolean containsTagInPath(List path, Attributes dcm) { + int size = path.size(); + if (size == 1) { + return dcm.contains(path.get(0)); + } + + List list = new ArrayList<>(); + + for (int i = 0; i < size; i++) { + int tag = path.get(i); + if (i == size - 1) { + for (Attributes item : list) { + if (item.contains(tag)) { + return true; + } + } + return false; + } + + if (list.isEmpty()) { + list = dcm.getSequence(tag); + } + else { + list = getChildSequences(list, tag); + } + + if (list == null || list.isEmpty()) { + return false; + } + } + + return false; + } + + private static List getChildSequences(List seq, int seqTag) { + if (seq != null) { + List items = new ArrayList<>(); + for (Attributes item : seq) { + Sequence childSeq = item.getSequence(seqTag); + if (childSeq != null) { + items.addAll(childSeq); + } + } + return items; + } + return null; + } + + public static boolean containsTagInAllAttributes(int tag, Attributes dcm) { + if (dcm.contains(tag)) { + return true; + } + for (int t : dcm.tags()) { + if (dcm.getVR(t) == VR.SQ) { + Sequence seq = dcm.getSequence(t); + if (seq != null) { + for (Attributes item : seq) { + boolean result = containsTagInAllAttributes(tag, item); + if (result) { + return true; + } + } + } + } + } + return false; + } + } diff --git a/src/main/java/org/karnak/backend/util/DoubleToIntegerConverter.java b/src/main/java/org/karnak/backend/util/DoubleToIntegerConverter.java index 620f35cb2..294011251 100644 --- a/src/main/java/org/karnak/backend/util/DoubleToIntegerConverter.java +++ b/src/main/java/org/karnak/backend/util/DoubleToIntegerConverter.java @@ -15,23 +15,26 @@ public class DoubleToIntegerConverter implements Converter { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - @Override - public Result convertToModel(Double value, ValueContext valueContext) { - if (value != null) { - return Result.ok(value.intValue()); - } else { - return Result.ok(null); - } - } + @Override + public Result convertToModel(Double value, ValueContext valueContext) { + if (value != null) { + return Result.ok(value.intValue()); + } + else { + return Result.ok(null); + } + } + + @Override + public Double convertToPresentation(Integer value, ValueContext valueContext) { + if (value == null) { + return null; + } + else { + return value.doubleValue(); + } + } - @Override - public Double convertToPresentation(Integer value, ValueContext valueContext) { - if (value == null) { - return null; - } else { - return value.doubleValue(); - } - } } diff --git a/src/main/java/org/karnak/backend/util/MetadataDICOMObject.java b/src/main/java/org/karnak/backend/util/MetadataDICOMObject.java index bcc1e7e93..c0e830980 100644 --- a/src/main/java/org/karnak/backend/util/MetadataDICOMObject.java +++ b/src/main/java/org/karnak/backend/util/MetadataDICOMObject.java @@ -14,38 +14,38 @@ public class MetadataDICOMObject { - /* - * Search a tagValue in the current DicomObject and his parent - * Will loop in the parent of the DicomObject until the last parent or the tagValue - * */ - public static String getValue(Attributes dcm, int tag) { - return getValueRec(dcm, tag); - } + /* + * Search a tagValue in the current DicomObject and his parent Will loop in the parent + * of the DicomObject until the last parent or the tagValue + */ + public static String getValue(Attributes dcm, int tag) { + return getValueRec(dcm, tag); + } - private static String getValueRec(Attributes dcm, int tag) { - String tagValue = dcm.getString(tag); - Attributes dcmParent = dcm.getParent(); - if (dcmParent != null && tagValue == null) { - return getValueRec(dcmParent, tag); - } - return tagValue; - } + private static String getValueRec(Attributes dcm, int tag) { + String tagValue = dcm.getString(tag); + Attributes dcmParent = dcm.getParent(); + if (dcmParent != null && tagValue == null) { + return getValueRec(dcmParent, tag); + } + return tagValue; + } - /* - * Generate the tag Path as needed in the class StandardDICOM - * Will loop in the parent of the DicomObject until the last parent - * */ - public static String getTagPath(Attributes dcm, int currentTag) { - return getTagPathRec(dcm, TagUtils.toString(currentTag)); - } + /* + * Generate the tag Path as needed in the class StandardDICOM Will loop in the parent + * of the DicomObject until the last parent + */ + public static String getTagPath(Attributes dcm, int currentTag) { + return getTagPathRec(dcm, TagUtils.toString(currentTag)); + } + + private static String getTagPathRec(Attributes dcm, String tagPath) { + Attributes dcmParent = dcm.getParent(); + if (dcmParent != null) { + return getTagPathRec(dcmParent, + String.format("%s:%s", TagUtils.toHexString(dcm.getParentSequenceTag()), tagPath)); + } + return tagPath; + } - private static String getTagPathRec(Attributes dcm, String tagPath) { - Attributes dcmParent = dcm.getParent(); - if (dcmParent != null) { - return getTagPathRec( - dcmParent, - String.format("%s:%s", TagUtils.toHexString(dcm.getParentSequenceTag()), tagPath)); - } - return tagPath; - } } diff --git a/src/main/java/org/karnak/backend/util/NativeLibraryManager.java b/src/main/java/org/karnak/backend/util/NativeLibraryManager.java index c3966a1ec..68cc16540 100644 --- a/src/main/java/org/karnak/backend/util/NativeLibraryManager.java +++ b/src/main/java/org/karnak/backend/util/NativeLibraryManager.java @@ -24,36 +24,35 @@ public class NativeLibraryManager { - private static final Logger LOGGER = LoggerFactory.getLogger(NativeLibraryManager.class); - - private NativeLibraryManager() {} - - public static void initNativeLibs(URL resource) { - Optional oLibPath = - Arrays.stream(System.getProperty("java.library.path").split(File.pathSeparator)) - .filter(p -> p.contains("dicom-opencv")) - .findFirst(); - if (oLibPath.isEmpty()) { - throw new IllegalStateException("OpenCV library is not configured in java.library.path"); - } - - String system = NativeLibrary.getNativeLibSpecification(); - String filename = - system.startsWith("win") - ? "opencv_java.dll" - : system.startsWith("mac") ? "libopencv_java.dylib" : "libopencv_java.so"; - Path outputFile = Path.of(oLibPath.get(), filename); - System.setProperty("dicom.native.codec", oLibPath.get()); - - try { - Files.createDirectories(outputFile.getParent()); - String path = resource.toString() + "/" + system + "/" + filename; - FileUtil.writeStream(new URL(path).openStream(), outputFile, true); - } catch (IOException e) { - LOGGER.error("copy native libs", e); - } - - OpenCVNativeLoader loader = new OpenCVNativeLoader(); - loader.init(); - } + private static final Logger LOGGER = LoggerFactory.getLogger(NativeLibraryManager.class); + + private NativeLibraryManager() { + } + + public static void initNativeLibs(URL resource) { + Optional oLibPath = Arrays.stream(System.getProperty("java.library.path").split(File.pathSeparator)) + .filter(p -> p.contains("dicom-opencv")).findFirst(); + if (oLibPath.isEmpty()) { + throw new IllegalStateException("OpenCV library is not configured in java.library.path"); + } + + String system = NativeLibrary.getNativeLibSpecification(); + String filename = system.startsWith("win") ? "opencv_java.dll" + : system.startsWith("mac") ? "libopencv_java.dylib" : "libopencv_java.so"; + Path outputFile = Path.of(oLibPath.get(), filename); + System.setProperty("dicom.native.codec", oLibPath.get()); + + try { + Files.createDirectories(outputFile.getParent()); + String path = resource.toString() + "/" + system + "/" + filename; + FileUtil.writeStream(new URL(path).openStream(), outputFile, true); + } + catch (IOException e) { + LOGGER.error("copy native libs", e); + } + + OpenCVNativeLoader loader = new OpenCVNativeLoader(); + loader.init(); + } + } diff --git a/src/main/java/org/karnak/backend/util/PatientClientUtil.java b/src/main/java/org/karnak/backend/util/PatientClientUtil.java index 8b7b2a2e4..03ba10b63 100644 --- a/src/main/java/org/karnak/backend/util/PatientClientUtil.java +++ b/src/main/java/org/karnak/backend/util/PatientClientUtil.java @@ -15,59 +15,58 @@ public class PatientClientUtil { - private PatientClientUtil() { - throw new IllegalStateException("Utility class"); - } + private PatientClientUtil() { + throw new IllegalStateException("Utility class"); + } - public static String getPseudonym(PatientMetadata patientMetadata, PatientClient cache) { - if (cache != null) { - final String key = generateKey(patientMetadata); - return getCachedKey(key, patientMetadata, cache); - } - return null; - } + public static String getPseudonym(PatientMetadata patientMetadata, PatientClient cache) { + if (cache != null) { + final String key = generateKey(patientMetadata); + return getCachedKey(key, patientMetadata, cache); + } + return null; + } - public static String getPseudonym( - PatientMetadata patientMetadata, PatientClient cache, Long projectID) { - if (cache != null) { - final String key = generateKey(patientMetadata, projectID); - return getCachedKey(key, patientMetadata, cache); - } - return null; - } + public static String getPseudonym(PatientMetadata patientMetadata, PatientClient cache, Long projectID) { + if (cache != null) { + final String key = generateKey(patientMetadata, projectID); + return getCachedKey(key, patientMetadata, cache); + } + return null; + } - private static String getCachedKey( - String key, PatientMetadata patientMetadata, PatientClient cache) { - final PseudonymPatient patient = cache.get(key); - if (patient != null && patientMetadata.compareCachedPatient(patient)) { - return patient.getPseudonym(); - } - return null; - } + private static String getCachedKey(String key, PatientMetadata patientMetadata, PatientClient cache) { + final PseudonymPatient patient = cache.get(key); + if (patient != null && patientMetadata.compareCachedPatient(patient)) { + return patient.getPseudonym(); + } + return null; + } - public static String generateKey(String patientID, String issuerOfPatientID) { - return patientID.concat(issuerOfPatientID == null ? "" : issuerOfPatientID); - } + public static String generateKey(String patientID, String issuerOfPatientID) { + return patientID.concat(issuerOfPatientID == null ? "" : issuerOfPatientID); + } - public static String generateKey(PseudonymPatient patient) { - String patientID = patient.getPatientId(); - String issuerOfPatientID = patient.getIssuerOfPatientId(); - return generateKey(patientID, issuerOfPatientID); - } + public static String generateKey(PseudonymPatient patient) { + String patientID = patient.getPatientId(); + String issuerOfPatientID = patient.getIssuerOfPatientId(); + return generateKey(patientID, issuerOfPatientID); + } - public static String generateKey(PatientMetadata patientMetadata) { - String patientID = patientMetadata.getPatientID(); - String issuerOfPatientID = patientMetadata.getIssuerOfPatientID(); - return generateKey(patientID, issuerOfPatientID); - } + public static String generateKey(PatientMetadata patientMetadata) { + String patientID = patientMetadata.getPatientID(); + String issuerOfPatientID = patientMetadata.getIssuerOfPatientID(); + return generateKey(patientID, issuerOfPatientID); + } - public static String generateKey(PatientMetadata patientMetadata, Long projectID) { - final String key = generateKey(patientMetadata); - return key.concat(projectID == null ? "" : projectID.toString()); - } + public static String generateKey(PatientMetadata patientMetadata, Long projectID) { + final String key = generateKey(patientMetadata); + return key.concat(projectID == null ? "" : projectID.toString()); + } + + public static String generateKey(PseudonymPatient pseudonymPatient, Long projectID) { + final String key = generateKey(pseudonymPatient); + return key.concat(projectID == null ? "" : projectID.toString()); + } - public static String generateKey(PseudonymPatient pseudonymPatient, Long projectID) { - final String key = generateKey(pseudonymPatient); - return key.concat(projectID == null ? "" : projectID.toString()); - } } diff --git a/src/main/java/org/karnak/backend/util/PrivateTagPattern.java b/src/main/java/org/karnak/backend/util/PrivateTagPattern.java index 0f80e8674..c60bcd03d 100644 --- a/src/main/java/org/karnak/backend/util/PrivateTagPattern.java +++ b/src/main/java/org/karnak/backend/util/PrivateTagPattern.java @@ -10,5 +10,7 @@ package org.karnak.backend.util; public class PrivateTagPattern { - public static final String TAG_PATTERN = "(GGGG,EEEE) WHERE GGGG IS ODD"; + + public static final String TAG_PATTERN = "(GGGG,EEEE) WHERE GGGG IS ODD"; + } diff --git a/src/main/java/org/karnak/backend/util/RandomUtils.java b/src/main/java/org/karnak/backend/util/RandomUtils.java index d41beb40f..d43b725c5 100644 --- a/src/main/java/org/karnak/backend/util/RandomUtils.java +++ b/src/main/java/org/karnak/backend/util/RandomUtils.java @@ -16,82 +16,75 @@ public class RandomUtils { - public static String generateAlphanumeric(int targetStringLength, Random random) { - int leftLimit = 48; // numeral '0' - int rightLimit = 122; // letter 'z' - String generatedString = - random - .ints(leftLimit, rightLimit + 1) - .filter(i -> (i <= 57 || i >= 65) && (i <= 90 || i >= 97)) - .limit(targetStringLength) - .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append) - .toString(); - return generatedString; - } + public static String generateAlphanumeric(int targetStringLength, Random random) { + int leftLimit = 48; // numeral '0' + int rightLimit = 122; // letter 'z' + String generatedString = random.ints(leftLimit, rightLimit + 1) + .filter(i -> (i <= 57 || i >= 65) && (i <= 90 || i >= 97)).limit(targetStringLength) + .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append).toString(); + return generatedString; + } - public static String generateUppercase(int targetStringLength, Random random) { - int leftLimit = 65; // numeral '0' - int rightLimit = 90; // letter 'z' - String generatedString = - random - .ints(leftLimit, rightLimit + 1) - .limit(targetStringLength) - .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append) - .toString(); - return generatedString; - } + public static String generateUppercase(int targetStringLength, Random random) { + int leftLimit = 65; // numeral '0' + int rightLimit = 90; // letter 'z' + String generatedString = random.ints(leftLimit, rightLimit + 1).limit(targetStringLength) + .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append).toString(); + return generatedString; + } - public static String generateNumeric(int min, int max, Random random) { - int randValue = createRandomIntBetween(min, max, random); - return Integer.toString(randValue); - } + public static String generateNumeric(int min, int max, Random random) { + int randValue = createRandomIntBetween(min, max, random); + return Integer.toString(randValue); + } - public static String generateBinary(int min, int max, Random random) { - int randValue = createRandomIntBetween(min, max, random); - return Integer.toBinaryString(randValue); - } + public static String generateBinary(int min, int max, Random random) { + int randValue = createRandomIntBetween(min, max, random); + return Integer.toBinaryString(randValue); + } - public static int createRandomIntBetween(int min, int max, Random random) { - return random.nextInt(max - min) + min; - } + public static int createRandomIntBetween(int min, int max, Random random) { + return random.nextInt(max - min) + min; + } - public static String randomAS(Random random) { - String format = "DWMY"; - char rndFormat = format.charAt(random.nextInt(format.length())); - return generateNumeric(0, 999, random) + rndFormat; - } + public static String randomAS(Random random) { + String format = "DWMY"; + char rndFormat = format.charAt(random.nextInt(format.length())); + return generateNumeric(0, 999, random) + rndFormat; + } - public static String randomDA(Random random) { - int day = createRandomIntBetween(1, 28, random); - int month = createRandomIntBetween(1, 12, random); - int year = createRandomIntBetween(1970, LocalDate.now().getYear(), random); - LocalDate date = LocalDate.of(year, month, day); - return DAtoString(date); - } + public static String randomDA(Random random) { + int day = createRandomIntBetween(1, 28, random); + int month = createRandomIntBetween(1, 12, random); + int year = createRandomIntBetween(1970, LocalDate.now().getYear(), random); + LocalDate date = LocalDate.of(year, month, day); + return DAtoString(date); + } - public static String DAtoString(LocalDate date) { - DateTimeFormatter formatDA = DateTimeFormatter.ofPattern("yyyyMMdd"); - String formattedDate = formatDA.format(date); - return formattedDate; - } + public static String DAtoString(LocalDate date) { + DateTimeFormatter formatDA = DateTimeFormatter.ofPattern("yyyyMMdd"); + String formattedDate = formatDA.format(date); + return formattedDate; + } - public static String randomTM(Random random) { - int hour = createRandomIntBetween(0, 23, random); - int minute = createRandomIntBetween(0, 59, random); - int second = createRandomIntBetween(0, 59, random); - LocalTime time = LocalTime.of(hour, minute, second); - return TMtoString(time); - } + public static String randomTM(Random random) { + int hour = createRandomIntBetween(0, 23, random); + int minute = createRandomIntBetween(0, 59, random); + int second = createRandomIntBetween(0, 59, random); + LocalTime time = LocalTime.of(hour, minute, second); + return TMtoString(time); + } - public static String TMtoString(LocalTime time) { - DateTimeFormatter formatTM = DateTimeFormatter.ofPattern("HHmmss"); - String formattedTM = formatTM.format(time); - return formattedTM; - } + public static String TMtoString(LocalTime time) { + DateTimeFormatter formatTM = DateTimeFormatter.ofPattern("HHmmss"); + String formattedTM = formatTM.format(time); + return formattedTM; + } + + public static String randomDT(Random random) { + String stringDateTime = randomDA(random); + stringDateTime = stringDateTime.concat(randomTM(random)); + return stringDateTime; + } - public static String randomDT(Random random) { - String stringDateTime = randomDA(random); - stringDateTime = stringDateTime.concat(randomTM(random)); - return stringDateTime; - } } diff --git a/src/main/java/org/karnak/backend/util/SecurityUtil.java b/src/main/java/org/karnak/backend/util/SecurityUtil.java index 5698d5ab1..5e8def692 100644 --- a/src/main/java/org/karnak/backend/util/SecurityUtil.java +++ b/src/main/java/org/karnak/backend/util/SecurityUtil.java @@ -32,81 +32,74 @@ @Component public final class SecurityUtil { - private static final Logger LOG = LoggerFactory.getLogger(SecurityUtil.class); + private static final Logger LOG = LoggerFactory.getLogger(SecurityUtil.class); - /** - * Determines if a request is internal to Vaadin - * - * @param request Request - * @return true if it is a internal request - */ - public static boolean isFrameworkInternalRequest(HttpServletRequest request) { - final String parameterValue = request.getParameter(ApplicationConstants.REQUEST_TYPE_PARAMETER); - return parameterValue != null - && Stream.of(HandlerHelper.RequestType.values()) - .anyMatch(r -> r.getIdentifier().equals(parameterValue)); - } + /** + * Determines if a request is internal to Vaadin + * @param request Request + * @return true if it is a internal request + */ + public static boolean isFrameworkInternalRequest(HttpServletRequest request) { + final String parameterValue = request.getParameter(ApplicationConstants.REQUEST_TYPE_PARAMETER); + return parameterValue != null && Stream.of(HandlerHelper.RequestType.values()) + .anyMatch(r -> r.getIdentifier().equals(parameterValue)); + } - /** - * Checks if the current user is logged in - * - * @return true if the current user is logged in - */ - public static boolean isUserLoggedIn() { - Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - return authentication != null - && !(authentication instanceof AnonymousAuthenticationToken) - && authentication.isAuthenticated(); - } + /** + * Checks if the current user is logged in + * @return true if the current user is logged in + */ + public static boolean isUserLoggedIn() { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + return authentication != null && !(authentication instanceof AnonymousAuthenticationToken) + && authentication.isAuthenticated(); + } - /** - * Checks if the user is logged and is an admin - * - * @return true if the user is logged and is an admin - */ - public static boolean isUserAdmin() { - return SecurityUtil.isUserLoggedIn() - && SecurityContextHolder.getContext().getAuthentication().getAuthorities().stream() - .anyMatch(ga -> Objects.equals(ga.getAuthority(), SecurityRole.ADMIN_ROLE.getRole())); - } + /** + * Checks if the user is logged and is an admin + * @return true if the user is logged and is an admin + */ + public static boolean isUserAdmin() { + return SecurityUtil.isUserLoggedIn() && SecurityContextHolder.getContext().getAuthentication().getAuthorities() + .stream().anyMatch(ga -> Objects.equals(ga.getAuthority(), SecurityRole.ADMIN_ROLE.getRole())); + } - /** - * Check if the role of the user can access the view - * - * @param securedClass Secured Class - * @return true if access is granted - */ - public static boolean isAccessGranted(Class securedClass) { - boolean isAccessGranted = false; + /** + * Check if the role of the user can access the view + * @param securedClass Secured Class + * @return true if access is granted + */ + public static boolean isAccessGranted(Class securedClass) { + boolean isAccessGranted = false; - if (isUserLoggedIn()) { - // get the secured annotation - Secured secured = AnnotationUtils.findAnnotation(securedClass, Secured.class); + if (isUserLoggedIn()) { + // get the secured annotation + Secured secured = AnnotationUtils.findAnnotation(securedClass, Secured.class); - // allow if no roles are required - if (secured == null) { - isAccessGranted = true; - } else { - // lookup needed role in user roles - List allowedRoles = Arrays.asList(secured.value()); + // allow if no roles are required + if (secured == null) { + isAccessGranted = true; + } + else { + // lookup needed role in user roles + List allowedRoles = Arrays.asList(secured.value()); - Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - isAccessGranted = - authentication != null - && authentication.getAuthorities().stream() - .map(GrantedAuthority::getAuthority) - .anyMatch(allowedRoles::contains); - } - } - return isAccessGranted; - } + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + isAccessGranted = authentication != null && authentication.getAuthorities().stream() + .map(GrantedAuthority::getAuthority).anyMatch(allowedRoles::contains); + } + } + return isAccessGranted; + } + + /** Sign out method */ + public static void signOut() { + try { + VaadinServletService.getCurrentServletRequest().logout(); + } + catch (ServletException e) { + LOG.error("Error during logout"); + } + } - /** Sign out method */ - public static void signOut() { - try { - VaadinServletService.getCurrentServletRequest().logout(); - } catch (ServletException e) { - LOG.error("Error during logout"); - } - } } diff --git a/src/main/java/org/karnak/backend/util/ServletUtil.java b/src/main/java/org/karnak/backend/util/ServletUtil.java index 0aa9d8785..3bf18aecb 100644 --- a/src/main/java/org/karnak/backend/util/ServletUtil.java +++ b/src/main/java/org/karnak/backend/util/ServletUtil.java @@ -23,151 +23,162 @@ public class ServletUtil { - private static final Logger LOGGER = LoggerFactory.getLogger(ServletUtil.class); - - private ServletUtil() {} - - public static String getFirstParameter(Object val) { - if (val instanceof String[]) { - String[] params = (String[]) val; - if (params.length > 0) { - return params[0]; - } - } else if (val != null) { - return val.toString(); - } - return null; - } - - public static String[] getParameters(Object val) { - if (val instanceof String[]) { - return (String[]) val; - } else if (val != null) { - return new String[] {val.toString()}; - } - return null; - } - - public static Object addParameter(Object val, String arg) { - if (val instanceof String[]) { - String[] array = (String[]) val; - String[] arr = Arrays.copyOf(array, array.length + 1); - arr[array.length] = arg; - return arr; - } else if (val != null) { - return new String[] {val.toString(), arg}; - } - return arg; - } - - public static int getIntProperty(Properties prop, String key, int def) { - int result = def; - final String value = prop.getProperty(key); - if (value != null) { - try { - result = Integer.parseInt(value); - } catch (NumberFormatException ignore) { - // return the default value - } - } - return result; - } - - public static long getLongProperty(Properties prop, String key, long def) { - long result = def; - final String value = prop.getProperty(key); - if (value != null) { - try { - result = Long.parseLong(value); - } catch (NumberFormatException ignore) { - // return the default value - } - } - return result; - } - - public static void write(InputStream in, OutputStream out) throws IOException { - try { - copy(in, out, 2048); - } catch (Exception e) { - handleException(e); - } finally { - try { - in.close(); - out.flush(); - } catch (IOException e) { - // jetty 6 throws broken pipe exception here too - handleException(e); - } - } - } - - private static int copy(final InputStream in, final OutputStream out, final int bufSize) - throws IOException { - final byte[] buffer = new byte[bufSize]; - int bytesCopied = 0; - while (true) { - int byteCount = in.read(buffer, 0, buffer.length); - if (byteCount <= 0) { - break; - } - out.write(buffer, 0, byteCount); - bytesCopied += byteCount; - } - return bytesCopied; - } - - private static void handleException(Exception e) { - Throwable throwable = e; - boolean ignoreException = false; - while (throwable != null) { - if (throwable instanceof SQLException) { - break; // leave false and quit loop - } else if (throwable instanceof SocketException) { - String message = throwable.getMessage(); - ignoreException = - message != null - && (message.indexOf("Connection reset") != -1 - || message.indexOf("Broken pipe") != -1 - || message.indexOf("Socket closed") != -1 - || message.indexOf("connection abort") != -1); - } else { - ignoreException = - throwable.getClass().getName().indexOf("ClientAbortException") >= 0 - || throwable.getClass().getName().indexOf("EofException") >= 0; - } - if (ignoreException) { - break; - } - throwable = throwable.getCause(); - } - - if (!ignoreException) { - throw new IllegalStateException("Unable to write the response", e); - } - } - - public static void write(String str, ServletOutputStream out) { - try { - byte[] bytes = str.getBytes(); - out.write(bytes, 0, bytes.length); - } catch (Exception e) { - handleException(e); - } finally { - try { - out.flush(); - } catch (IOException e) { - // jetty 6 throws broken pipe exception here too - handleException(e); - } - } - } - - public static void sendResponseError(HttpServletResponse response, int code, String message) { - try { - response.sendError(code, message); - } catch (IOException e) { - LOGGER.error("Cannot send http response message!", e); - } - } + private static final Logger LOGGER = LoggerFactory.getLogger(ServletUtil.class); + + private ServletUtil() { + } + + public static String getFirstParameter(Object val) { + if (val instanceof String[]) { + String[] params = (String[]) val; + if (params.length > 0) { + return params[0]; + } + } + else if (val != null) { + return val.toString(); + } + return null; + } + + public static String[] getParameters(Object val) { + if (val instanceof String[]) { + return (String[]) val; + } + else if (val != null) { + return new String[] { val.toString() }; + } + return null; + } + + public static Object addParameter(Object val, String arg) { + if (val instanceof String[]) { + String[] array = (String[]) val; + String[] arr = Arrays.copyOf(array, array.length + 1); + arr[array.length] = arg; + return arr; + } + else if (val != null) { + return new String[] { val.toString(), arg }; + } + return arg; + } + + public static int getIntProperty(Properties prop, String key, int def) { + int result = def; + final String value = prop.getProperty(key); + if (value != null) { + try { + result = Integer.parseInt(value); + } + catch (NumberFormatException ignore) { + // return the default value + } + } + return result; + } + + public static long getLongProperty(Properties prop, String key, long def) { + long result = def; + final String value = prop.getProperty(key); + if (value != null) { + try { + result = Long.parseLong(value); + } + catch (NumberFormatException ignore) { + // return the default value + } + } + return result; + } + + public static void write(InputStream in, OutputStream out) throws IOException { + try { + copy(in, out, 2048); + } + catch (Exception e) { + handleException(e); + } + finally { + try { + in.close(); + out.flush(); + } + catch (IOException e) { + // jetty 6 throws broken pipe exception here too + handleException(e); + } + } + } + + private static int copy(final InputStream in, final OutputStream out, final int bufSize) throws IOException { + final byte[] buffer = new byte[bufSize]; + int bytesCopied = 0; + while (true) { + int byteCount = in.read(buffer, 0, buffer.length); + if (byteCount <= 0) { + break; + } + out.write(buffer, 0, byteCount); + bytesCopied += byteCount; + } + return bytesCopied; + } + + private static void handleException(Exception e) { + Throwable throwable = e; + boolean ignoreException = false; + while (throwable != null) { + if (throwable instanceof SQLException) { + break; // leave false and quit loop + } + else if (throwable instanceof SocketException) { + String message = throwable.getMessage(); + ignoreException = message != null + && (message.indexOf("Connection reset") != -1 || message.indexOf("Broken pipe") != -1 + || message.indexOf("Socket closed") != -1 || message.indexOf("connection abort") != -1); + } + else { + ignoreException = throwable.getClass().getName().indexOf("ClientAbortException") >= 0 + || throwable.getClass().getName().indexOf("EofException") >= 0; + } + if (ignoreException) { + break; + } + throwable = throwable.getCause(); + } + + if (!ignoreException) { + throw new IllegalStateException("Unable to write the response", e); + } + } + + public static void write(String str, ServletOutputStream out) { + try { + byte[] bytes = str.getBytes(); + out.write(bytes, 0, bytes.length); + } + catch (Exception e) { + handleException(e); + } + finally { + try { + out.flush(); + } + catch (IOException e) { + // jetty 6 throws broken pipe exception here too + handleException(e); + } + } + } + + public static void sendResponseError(HttpServletResponse response, int code, String message) { + try { + response.sendError(code, message); + } + catch (IOException e) { + LOGGER.error("Cannot send http response message!", e); + } + } + } diff --git a/src/main/java/org/karnak/backend/util/ShiftDate.java b/src/main/java/org/karnak/backend/util/ShiftDate.java index 5ba810e78..88c499199 100644 --- a/src/main/java/org/karnak/backend/util/ShiftDate.java +++ b/src/main/java/org/karnak/backend/util/ShiftDate.java @@ -26,102 +26,101 @@ import org.weasis.dicom.util.DateUtil; public class ShiftDate { - private static final Logger LOGGER = LoggerFactory.getLogger(ShiftDate.class); - - private ShiftDate() {} - - public static String dateByDays(String date, int shiftDays) { - LocalDate localDate = DateTimeUtils.parseDA(date); - LocalDate dummyLocalDate = localDate.minusDays(shiftDays); - return DateUtil.formatDicomDate(dummyLocalDate); - } - - public static String timeBySeconds(String time, int shiftSeconds) { - LocalTime localTime = DateTimeUtils.parseTM(time); - LocalTime dummyLocalTime = localTime.minusSeconds(shiftSeconds); - return DateUtil.formatDicomTime(dummyLocalTime); - } - - public static String datetimeByDays(Date dateTime, int shiftDays, int shiftSeconds) { - LocalDateTime localDateTime = - LocalDateTime.ofInstant(dateTime.toInstant(), ZoneId.systemDefault()); - LocalDateTime dummyLocalDateTime = localDateTime.minusDays(shiftDays); - dummyLocalDateTime = dummyLocalDateTime.minusSeconds(shiftSeconds); - return DateTimeUtils.formatDT(dummyLocalDateTime); - } - - private static String addMissingZero(String age, int nMissingValue) { - int n = nMissingValue - age.length(); - return StringUtils.repeat('0', n) + age; - } - - public static String ageByDays(String age, int shiftDays) { - String valueAge = age.substring(0, 3); - int intAge = Integer.parseInt(valueAge); - - int maxSubstring = age.length(); - String formatAge = age.substring(3, maxSubstring); - - int intDummyAge = - switch (formatAge) { - case "Y" -> intAge + shiftDays / 365; - case "M" -> intAge + shiftDays / 30; - case "W" -> intAge + shiftDays / 7; - default -> intAge + shiftDays; - }; - - return addMissingZero(String.valueOf(intDummyAge), 3) + formatAge; - } - - public static String shift(Attributes dcm, int tag, List argumentEntities) - throws DateTimeException { - verifyShiftArguments(argumentEntities); - - String dcmElValue = dcm.getString(tag); - int shiftDays = -1; - int shiftSeconds = -1; - - for (ArgumentEntity argumentEntity : argumentEntities) { - final String key = argumentEntity.getKey(); - final String value = argumentEntity.getValue(); - - try { - if (key.equals("seconds")) { - shiftSeconds = Integer.parseInt(value); - } - if (key.equals("days")) { - shiftDays = Integer.parseInt(value); - } - } catch (Exception e) { - LOGGER.error("args {} is not correct", value, e); - } - } - if (dcmElValue != null) { - return switch (dcm.getVR(tag)) { - case AS -> ageByDays(dcmElValue, shiftDays); - case DA -> dateByDays(dcmElValue, shiftDays); - case DT -> datetimeByDays(dcm.getDate(tag), shiftDays, shiftSeconds); - case TM -> timeBySeconds(dcmElValue, shiftSeconds); - default -> null; - }; - } else { - return null; - } - } - - public static void verifyShiftArguments(List argumentEntities) - throws IllegalArgumentException { - if (argumentEntities.stream().noneMatch(argument -> argument.getKey().equals("seconds")) - || argumentEntities.stream().noneMatch(argument -> argument.getKey().equals("days"))) { - List args = - argumentEntities.stream().map(ArgumentEntity::getKey).collect(Collectors.toList()); - IllegalArgumentException missingParameters = - new IllegalArgumentException( - "Cannot build the option ShiftDate: Missing argument, the class need [seconds, days] as parameters. Parameters given " - + args); - LOGGER.error( - "Missing argument, the class need seconds and days as parameters", missingParameters); - throw missingParameters; - } - } + + private static final Logger LOGGER = LoggerFactory.getLogger(ShiftDate.class); + + private ShiftDate() { + } + + public static String dateByDays(String date, int shiftDays) { + LocalDate localDate = DateTimeUtils.parseDA(date); + LocalDate dummyLocalDate = localDate.minusDays(shiftDays); + return DateUtil.formatDicomDate(dummyLocalDate); + } + + public static String timeBySeconds(String time, int shiftSeconds) { + LocalTime localTime = DateTimeUtils.parseTM(time); + LocalTime dummyLocalTime = localTime.minusSeconds(shiftSeconds); + return DateUtil.formatDicomTime(dummyLocalTime); + } + + public static String datetimeByDays(Date dateTime, int shiftDays, int shiftSeconds) { + LocalDateTime localDateTime = LocalDateTime.ofInstant(dateTime.toInstant(), ZoneId.systemDefault()); + LocalDateTime dummyLocalDateTime = localDateTime.minusDays(shiftDays); + dummyLocalDateTime = dummyLocalDateTime.minusSeconds(shiftSeconds); + return DateTimeUtils.formatDT(dummyLocalDateTime); + } + + private static String addMissingZero(String age, int nMissingValue) { + int n = nMissingValue - age.length(); + return StringUtils.repeat('0', n) + age; + } + + public static String ageByDays(String age, int shiftDays) { + String valueAge = age.substring(0, 3); + int intAge = Integer.parseInt(valueAge); + + int maxSubstring = age.length(); + String formatAge = age.substring(3, maxSubstring); + + int intDummyAge = switch (formatAge) { + case "Y" -> intAge + shiftDays / 365; + case "M" -> intAge + shiftDays / 30; + case "W" -> intAge + shiftDays / 7; + default -> intAge + shiftDays; + }; + + return addMissingZero(String.valueOf(intDummyAge), 3) + formatAge; + } + + public static String shift(Attributes dcm, int tag, List argumentEntities) + throws DateTimeException { + verifyShiftArguments(argumentEntities); + + String dcmElValue = dcm.getString(tag); + int shiftDays = -1; + int shiftSeconds = -1; + + for (ArgumentEntity argumentEntity : argumentEntities) { + final String key = argumentEntity.getKey(); + final String value = argumentEntity.getValue(); + + try { + if (key.equals("seconds")) { + shiftSeconds = Integer.parseInt(value); + } + if (key.equals("days")) { + shiftDays = Integer.parseInt(value); + } + } + catch (Exception e) { + LOGGER.error("args {} is not correct", value, e); + } + } + if (dcmElValue != null) { + return switch (dcm.getVR(tag)) { + case AS -> ageByDays(dcmElValue, shiftDays); + case DA -> dateByDays(dcmElValue, shiftDays); + case DT -> datetimeByDays(dcm.getDate(tag), shiftDays, shiftSeconds); + case TM -> timeBySeconds(dcmElValue, shiftSeconds); + default -> null; + }; + } + else { + return null; + } + } + + public static void verifyShiftArguments(List argumentEntities) throws IllegalArgumentException { + if (argumentEntities.stream().noneMatch(argument -> argument.getKey().equals("seconds")) + || argumentEntities.stream().noneMatch(argument -> argument.getKey().equals("days"))) { + List args = argumentEntities.stream().map(ArgumentEntity::getKey).collect(Collectors.toList()); + IllegalArgumentException missingParameters = new IllegalArgumentException( + "Cannot build the option ShiftDate: Missing argument, the class need [seconds, days] as parameters. Parameters given " + + args); + LOGGER.error("Missing argument, the class need seconds and days as parameters", missingParameters); + throw missingParameters; + } + } + } diff --git a/src/main/java/org/karnak/backend/util/ShiftRangeDate.java b/src/main/java/org/karnak/backend/util/ShiftRangeDate.java index 05f6bd8a5..abbe2887d 100644 --- a/src/main/java/org/karnak/backend/util/ShiftRangeDate.java +++ b/src/main/java/org/karnak/backend/util/ShiftRangeDate.java @@ -20,74 +20,74 @@ public class ShiftRangeDate { - private static final Logger LOGGER = LoggerFactory.getLogger(ShiftRangeDate.class); + private static final Logger LOGGER = LoggerFactory.getLogger(ShiftRangeDate.class); - private ShiftRangeDate() {} + private ShiftRangeDate() { + } - public static void verifyShiftArguments(List argumentEntities) - throws IllegalArgumentException { - if (argumentEntities.stream().noneMatch(argument -> argument.getKey().equals("max_seconds")) - || argumentEntities.stream().noneMatch(argument -> argument.getKey().equals("max_days"))) { - List args = - argumentEntities.stream().map(ArgumentEntity::getKey).collect(Collectors.toList()); - String text = - "Cannot build the option ShiftRangeDate: Missing argument, the class minimum need [max_seconds, max_days] as parameters. Parameters given " - + args; + public static void verifyShiftArguments(List argumentEntities) throws IllegalArgumentException { + if (argumentEntities.stream().noneMatch(argument -> argument.getKey().equals("max_seconds")) + || argumentEntities.stream().noneMatch(argument -> argument.getKey().equals("max_days"))) { + List args = argumentEntities.stream().map(ArgumentEntity::getKey).collect(Collectors.toList()); + String text = "Cannot build the option ShiftRangeDate: Missing argument, the class minimum need [max_seconds, max_days] as parameters. Parameters given " + + args; - IllegalArgumentException missingParameters = new IllegalArgumentException(text); - LOGGER.error(text, missingParameters); - throw missingParameters; - } - } + IllegalArgumentException missingParameters = new IllegalArgumentException(text); + LOGGER.error(text, missingParameters); + throw missingParameters; + } + } - public static String shift( - Attributes dcm, int tag, List argumentEntities, HMAC hmac) - throws DateTimeException { - try { - verifyShiftArguments(argumentEntities); - } catch (IllegalArgumentException e) { - throw e; - } - int shiftMaxDays = -1; - int shiftMaxSeconds = -1; - int shiftMinDays = 0; - int shiftMinSeconds = 0; - for (ArgumentEntity argumentEntity : argumentEntities) { - final String key = argumentEntity.getKey(); - final String value = argumentEntity.getValue(); + public static String shift(Attributes dcm, int tag, List argumentEntities, HMAC hmac) + throws DateTimeException { + try { + verifyShiftArguments(argumentEntities); + } + catch (IllegalArgumentException e) { + throw e; + } + int shiftMaxDays = -1; + int shiftMaxSeconds = -1; + int shiftMinDays = 0; + int shiftMinSeconds = 0; + for (ArgumentEntity argumentEntity : argumentEntities) { + final String key = argumentEntity.getKey(); + final String value = argumentEntity.getValue(); - try { - if (key.equals("max_seconds")) { - shiftMaxSeconds = Integer.parseInt(value); - } - if (key.equals("max_days")) { - shiftMaxDays = Integer.parseInt(value); - } - if (key.equals("min_seconds")) { - shiftMinSeconds = Integer.parseInt(value); - } - if (key.equals("min_days")) { - shiftMinDays = Integer.parseInt(value); - } - } catch (Exception e) { - LOGGER.error("args {} is not correct", value, e); - } - } - String dcmElValue = dcm.getString(tag); - String patientID = hmac.getHashContext().getPatientID(); - int shiftDays = (int) hmac.scaleHash(patientID, shiftMinDays, shiftMaxDays); - int shiftSeconds = (int) hmac.scaleHash(patientID, shiftMinSeconds, shiftMaxSeconds); + try { + if (key.equals("max_seconds")) { + shiftMaxSeconds = Integer.parseInt(value); + } + if (key.equals("max_days")) { + shiftMaxDays = Integer.parseInt(value); + } + if (key.equals("min_seconds")) { + shiftMinSeconds = Integer.parseInt(value); + } + if (key.equals("min_days")) { + shiftMinDays = Integer.parseInt(value); + } + } + catch (Exception e) { + LOGGER.error("args {} is not correct", value, e); + } + } + String dcmElValue = dcm.getString(tag); + String patientID = hmac.getHashContext().getPatientID(); + int shiftDays = (int) hmac.scaleHash(patientID, shiftMinDays, shiftMaxDays); + int shiftSeconds = (int) hmac.scaleHash(patientID, shiftMinSeconds, shiftMaxSeconds); - if (dcmElValue != null) { - return switch (dcm.getVR(tag)) { - case AS -> ShiftDate.ageByDays(dcmElValue, shiftDays); - case DA -> ShiftDate.dateByDays(dcmElValue, shiftDays); - case DT -> ShiftDate.datetimeByDays(dcm.getDate(tag), shiftDays, shiftSeconds); - case TM -> ShiftDate.timeBySeconds(dcmElValue, shiftSeconds); - default -> null; - }; - } + if (dcmElValue != null) { + return switch (dcm.getVR(tag)) { + case AS -> ShiftDate.ageByDays(dcmElValue, shiftDays); + case DA -> ShiftDate.dateByDays(dcmElValue, shiftDays); + case DT -> ShiftDate.datetimeByDays(dcm.getDate(tag), shiftDays, shiftSeconds); + case TM -> ShiftDate.timeBySeconds(dcmElValue, shiftSeconds); + default -> null; + }; + } + + return null; + } - return null; - } } diff --git a/src/main/java/org/karnak/backend/util/SpecialCharacter.java b/src/main/java/org/karnak/backend/util/SpecialCharacter.java index 892e870cc..6561597d0 100644 --- a/src/main/java/org/karnak/backend/util/SpecialCharacter.java +++ b/src/main/java/org/karnak/backend/util/SpecialCharacter.java @@ -13,10 +13,11 @@ public class SpecialCharacter { - // Response Ferran Maylinch - // https://stackoverflow.com/questions/10664434/escaping-special-characters-in-java-regular-expressions - public static String escapeSpecialRegexChars(String str) { - Pattern SPECIAL_REGEX_CHARS = Pattern.compile("[{}()\\[\\].+*?^$\\\\|]"); - return SPECIAL_REGEX_CHARS.matcher(str).replaceAll("\\\\$0"); - } + // Response Ferran Maylinch + // https://stackoverflow.com/questions/10664434/escaping-special-characters-in-java-regular-expressions + public static String escapeSpecialRegexChars(String str) { + Pattern SPECIAL_REGEX_CHARS = Pattern.compile("[{}()\\[\\].+*?^$\\\\|]"); + return SPECIAL_REGEX_CHARS.matcher(str).replaceAll("\\\\$0"); + } + } diff --git a/src/main/java/org/karnak/backend/util/SpringDocUtil.java b/src/main/java/org/karnak/backend/util/SpringDocUtil.java index 10f2c85de..e37c4f635 100644 --- a/src/main/java/org/karnak/backend/util/SpringDocUtil.java +++ b/src/main/java/org/karnak/backend/util/SpringDocUtil.java @@ -10,18 +10,13 @@ package org.karnak.backend.util; public class SpringDocUtil { - /** Echo */ - // Examples - // Destinations (with status) - public static final String EXAMPLE_VALUES_STATUS_DESTINATIONS_ECHO = - "\n" - + " \n" - + " https://test.com/studies\n" - + " 0\n" - + " \n" - + " \n" - + " AET\n" - + " 0\n" - + " \n" - + ""; + + /** Echo */ + // Examples + // Destinations (with status) + public static final String EXAMPLE_VALUES_STATUS_DESTINATIONS_ECHO = "\n" + " \n" + + " https://test.com/studies\n" + " 0\n" + " \n" + + " \n" + " AET\n" + " 0\n" + + " \n" + ""; + } diff --git a/src/main/java/org/karnak/backend/util/SystemPropertyUtil.java b/src/main/java/org/karnak/backend/util/SystemPropertyUtil.java index 69fc24af7..c65232d29 100644 --- a/src/main/java/org/karnak/backend/util/SystemPropertyUtil.java +++ b/src/main/java/org/karnak/backend/util/SystemPropertyUtil.java @@ -13,23 +13,24 @@ public class SystemPropertyUtil { - private SystemPropertyUtil() {} + private SystemPropertyUtil() { + } + + /** + * Retrieve system property + * @param key Key + * @param defaultValue default value + * @return property found + */ + public static String retrieveSystemProperty(String key, String defaultValue) { + String val = System.getProperty(key); + if (!StringUtil.hasText(val)) { + val = System.getenv(key); + if (!StringUtil.hasText(val)) { + return defaultValue; + } + } + return val; + } - /** - * Retrieve system property - * - * @param key Key - * @param defaultValue default value - * @return property found - */ - public static String retrieveSystemProperty(String key, String defaultValue) { - String val = System.getProperty(key); - if (!StringUtil.hasText(val)) { - val = System.getenv(key); - if (!StringUtil.hasText(val)) { - return defaultValue; - } - } - return val; - } } diff --git a/src/main/java/org/karnak/frontend/AppShell.java b/src/main/java/org/karnak/frontend/AppShell.java index cfeeb9e59..f7bd933c7 100644 --- a/src/main/java/org/karnak/frontend/AppShell.java +++ b/src/main/java/org/karnak/frontend/AppShell.java @@ -14,9 +14,11 @@ import com.vaadin.flow.server.PWA; /** - * Use the @PWA annotation make the application installable on phones, tablets and some desktop - * browsers. + * Use the @PWA annotation make the application installable on phones, tablets and some + * desktop browsers. */ @PWA(name = "Karnak Gateway", shortName = "karnak", iconPath = "icons/logo.png") @Push -public class AppShell implements AppShellConfigurator {} +public class AppShell implements AppShellConfigurator { + +} diff --git a/src/main/java/org/karnak/frontend/ErrorView.java b/src/main/java/org/karnak/frontend/ErrorView.java index 7c68f533c..8dad1f14d 100644 --- a/src/main/java/org/karnak/frontend/ErrorView.java +++ b/src/main/java/org/karnak/frontend/ErrorView.java @@ -24,20 +24,20 @@ @SuppressWarnings("serial") public class ErrorView extends VerticalLayout implements HasErrorParameter { - private final Span explanation; + private final Span explanation; - public ErrorView() { - H1 header = new H1("The view could not be found."); - add(header); + public ErrorView() { + H1 header = new H1("The view could not be found."); + add(header); - explanation = new Span(); - add(explanation); - } + explanation = new Span(); + add(explanation); + } + + @Override + public int setErrorParameter(BeforeEnterEvent event, ErrorParameter parameter) { + explanation.setText("Could not navigate to '" + event.getLocation().getPath() + "'."); + return HttpServletResponse.SC_NOT_FOUND; + } - @Override - public int setErrorParameter( - BeforeEnterEvent event, ErrorParameter parameter) { - explanation.setText("Could not navigate to '" + event.getLocation().getPath() + "'."); - return HttpServletResponse.SC_NOT_FOUND; - } } diff --git a/src/main/java/org/karnak/frontend/MainLayout.java b/src/main/java/org/karnak/frontend/MainLayout.java index b99d23d7c..956c25e16 100644 --- a/src/main/java/org/karnak/frontend/MainLayout.java +++ b/src/main/java/org/karnak/frontend/MainLayout.java @@ -39,59 +39,53 @@ @CssImport(value = "./styles/shared-styles.css") @CssImport(value = "./styles/empty.css", include = "lumo-badge") @Route(value = "mainLayout") -@Secured({"ROLE_admin"}) +@Secured({ "ROLE_admin" }) @SuppressWarnings("serial") public class MainLayout extends FlexLayout implements RouterLayout { - private final Menu menu; + private final Menu menu; - public MainLayout() { - setSizeFull(); - setClassName("main-layout"); + public MainLayout() { + setSizeFull(); + setClassName("main-layout"); - menu = new Menu(); + menu = new Menu(); - // Add secured Menu - addSecuredMenu( - ForwardNodeView.class, ForwardNodeView.VIEW_NAME, new IronIcon("icons", "settings")); - addSecuredMenu(ProfileView.class, ProfileView.VIEW_NAME, new IronIcon("icons", "assignment")); - addSecuredMenu(ProjectView.class, ProjectView.VIEW_NAME, new IronIcon("icons", "class")); - addSecuredMenu( - ExternalIDView.class, ExternalIDView.VIEW_NAME, new IronIcon("icons", "perm-identity")); - addSecuredMenu( - MainzellisteView.class, MainzellisteView.VIEW_NAME, new IronIcon("icons", "perm-identity")); - addSecuredMenu( - PseudonymMappingView.class, - PseudonymMappingView.VIEW_NAME, - new IronIcon("icons", "perm-identity")); - addSecuredMenu( - MonitoringView.class, MonitoringView.VIEW_NAME, new IronIcon("icons", "history")); - addSecuredMenu(DicomMainView.class, DicomMainView.VIEW_NAME, new IronIcon("icons", "build")); - addSecuredMenu(HelpView.class, HelpView.VIEW_NAME, new IronIcon("icons", "help")); - // menu.addView(AboutView.class, AboutView.VIEW_NAME, new IronIcon("icons", "info")); + // Add secured Menu + addSecuredMenu(ForwardNodeView.class, ForwardNodeView.VIEW_NAME, new IronIcon("icons", "settings")); + addSecuredMenu(ProfileView.class, ProfileView.VIEW_NAME, new IronIcon("icons", "assignment")); + addSecuredMenu(ProjectView.class, ProjectView.VIEW_NAME, new IronIcon("icons", "class")); + addSecuredMenu(ExternalIDView.class, ExternalIDView.VIEW_NAME, new IronIcon("icons", "perm-identity")); + addSecuredMenu(MainzellisteView.class, MainzellisteView.VIEW_NAME, new IronIcon("icons", "perm-identity")); + addSecuredMenu(PseudonymMappingView.class, PseudonymMappingView.VIEW_NAME, + new IronIcon("icons", "perm-identity")); + addSecuredMenu(MonitoringView.class, MonitoringView.VIEW_NAME, new IronIcon("icons", "history")); + addSecuredMenu(DicomMainView.class, DicomMainView.VIEW_NAME, new IronIcon("icons", "build")); + addSecuredMenu(HelpView.class, HelpView.VIEW_NAME, new IronIcon("icons", "help")); + // menu.addView(AboutView.class, AboutView.VIEW_NAME, new IronIcon("icons", + // "info")); - // Add menu to the layout - add(menu); - } + // Add menu to the layout + add(menu); + } - @SuppressWarnings("rawtypes") - @Override - protected void onAttach(AttachEvent attachEvent) { - super.onAttach(attachEvent); - attachEvent.getUI().addShortcutListener(SecurityUtil::signOut, Key.KEY_L, KeyModifier.CONTROL); - } + @SuppressWarnings("rawtypes") + @Override + protected void onAttach(AttachEvent attachEvent) { + super.onAttach(attachEvent); + attachEvent.getUI().addShortcutListener(SecurityUtil::signOut, Key.KEY_L, KeyModifier.CONTROL); + } + + /** + * Build and add secured menus + * @param securedClass View to secure + * @param viewName Name of the view + * @param icon Icon to apply to the menu + */ + private void addSecuredMenu(Class securedClass, String viewName, IronIcon icon) { + if (SecurityUtil.isAccessGranted(securedClass)) { + menu.addView(securedClass, viewName, icon); + } + } - /** - * Build and add secured menus - * - * @param securedClass View to secure - * @param viewName Name of the view - * @param icon Icon to apply to the menu - */ - private void addSecuredMenu( - Class securedClass, String viewName, IronIcon icon) { - if (SecurityUtil.isAccessGranted(securedClass)) { - menu.addView(securedClass, viewName, icon); - } - } } diff --git a/src/main/java/org/karnak/frontend/Menu.java b/src/main/java/org/karnak/frontend/Menu.java index d9b3b6c95..c37331d6c 100644 --- a/src/main/java/org/karnak/frontend/Menu.java +++ b/src/main/java/org/karnak/frontend/Menu.java @@ -32,64 +32,65 @@ @SuppressWarnings("serial") public class Menu extends FlexLayout { - private static final String SHOW_TABS = "show-tabs"; - private final ToggleButtonTheme toggleButtonTheme; - private Tabs tabs; - private RadioButtonGroup radioGroup; + private static final String SHOW_TABS = "show-tabs"; - public Menu() { - setClassName("menu-bar"); + private final ToggleButtonTheme toggleButtonTheme; - // Button for toggling the menu visibility on small screens - final Button showMenu = - new Button( - "Menu", - event -> { - if (tabs.getClassNames().contains(SHOW_TABS)) { - tabs.removeClassName(SHOW_TABS); - } else { - tabs.addClassName(SHOW_TABS); - } - }); - showMenu.setClassName("menu-button"); - showMenu.addThemeVariants(ButtonVariant.LUMO_SMALL); - showMenu.setIcon(new Icon(VaadinIcon.MENU)); - add(showMenu); + private Tabs tabs; - // container for the navigation buttons, which are added by addView() - tabs = new Tabs(); - tabs.setOrientation(Tabs.Orientation.VERTICAL); - setFlexGrow(1, tabs); - add(tabs); + private RadioButtonGroup radioGroup; - // theme - toggleButtonTheme = new ToggleButtonTheme(); - VerticalLayout themeLayout = new VerticalLayout(toggleButtonTheme); - themeLayout.getElement().getStyle().set("align-items", "center"); - add(themeLayout); + public Menu() { + setClassName("menu-bar"); - // logout menu item - Button logoutButton = new Button("Logout", VaadinIcon.SIGN_OUT.create()); - logoutButton.addClickListener(event -> SecurityUtil.signOut()); + // Button for toggling the menu visibility on small screens + final Button showMenu = new Button("Menu", event -> { + if (tabs.getClassNames().contains(SHOW_TABS)) { + tabs.removeClassName(SHOW_TABS); + } + else { + tabs.addClassName(SHOW_TABS); + } + }); + showMenu.setClassName("menu-button"); + showMenu.addThemeVariants(ButtonVariant.LUMO_SMALL); + showMenu.setIcon(new Icon(VaadinIcon.MENU)); + add(showMenu); - logoutButton.addThemeVariants(ButtonVariant.LUMO_ERROR); - add(logoutButton); - } + // container for the navigation buttons, which are added by addView() + tabs = new Tabs(); + tabs.setOrientation(Tabs.Orientation.VERTICAL); + setFlexGrow(1, tabs); + add(tabs); + + // theme + toggleButtonTheme = new ToggleButtonTheme(); + VerticalLayout themeLayout = new VerticalLayout(toggleButtonTheme); + themeLayout.getElement().getStyle().set("align-items", "center"); + add(themeLayout); + + // logout menu item + Button logoutButton = new Button("Logout", VaadinIcon.SIGN_OUT.create()); + logoutButton.addClickListener(event -> SecurityUtil.signOut()); + + logoutButton.addThemeVariants(ButtonVariant.LUMO_ERROR); + add(logoutButton); + } + + /** + * Add a view to the navigation menu + * @param viewClass that has a {@code Route} annotation + * @param caption view caption in the menu + * @param icon view icon in the menu + */ + public void addView(Class viewClass, String caption, IronIcon icon) { + Tab tab = new Tab(); + RouterLink routerLink = new RouterLink(null, viewClass); + routerLink.setClassName("menu-link"); + routerLink.add(icon); + routerLink.add(new Span(caption)); + tab.add(routerLink); + tabs.add(tab); + } - /** - * Add a view to the navigation menu - * - * @param viewClass that has a {@code Route} annotation - * @param caption view caption in the menu - * @param icon view icon in the menu - */ - public void addView(Class viewClass, String caption, IronIcon icon) { - Tab tab = new Tab(); - RouterLink routerLink = new RouterLink(null, viewClass); - routerLink.setClassName("menu-link"); - routerLink.add(icon); - routerLink.add(new Span(caption)); - tab.add(routerLink); - tabs.add(tab); - } } diff --git a/src/main/java/org/karnak/frontend/about/AboutView.java b/src/main/java/org/karnak/frontend/about/AboutView.java index 256ad2987..f4133039e 100644 --- a/src/main/java/org/karnak/frontend/about/AboutView.java +++ b/src/main/java/org/karnak/frontend/about/AboutView.java @@ -18,15 +18,16 @@ @Route(value = "about", layout = MainLayout.class) @PageTitle("KARNAK - About") -@Secured({"ROLE_admin"}) +@Secured({ "ROLE_admin" }) @SuppressWarnings("serial") public class AboutView extends VerticalLayout { - public static final String VIEW_NAME = "About"; + public static final String VIEW_NAME = "About"; - public AboutView() { - add(new H2("About KARNAK")); + public AboutView() { + add(new H2("About KARNAK")); + + setSizeFull(); + } - setSizeFull(); - } } diff --git a/src/main/java/org/karnak/frontend/admin/AdminView.java b/src/main/java/org/karnak/frontend/admin/AdminView.java index dce6654da..d1778e066 100644 --- a/src/main/java/org/karnak/frontend/admin/AdminView.java +++ b/src/main/java/org/karnak/frontend/admin/AdminView.java @@ -18,9 +18,10 @@ @SuppressWarnings("serial") public class AdminView extends VerticalLayout { - public static final String VIEW_NAME = "Admin"; + public static final String VIEW_NAME = "Admin"; + + public AdminView() { + add(new H2("You are connected as an admin.")); + } - public AdminView() { - add(new H2("You are connected as an admin.")); - } } diff --git a/src/main/java/org/karnak/frontend/authentication/CurrentUser.java b/src/main/java/org/karnak/frontend/authentication/CurrentUser.java index 5f822d489..9e9b2e24f 100644 --- a/src/main/java/org/karnak/frontend/authentication/CurrentUser.java +++ b/src/main/java/org/karnak/frontend/authentication/CurrentUser.java @@ -13,60 +13,56 @@ import com.vaadin.flow.server.VaadinService; /** - * Class for retrieving and setting the name of the current user of the current session (without - * using JAAS). All methods of this class require that a {@link VaadinRequest} is bound to the - * current thread. + * Class for retrieving and setting the name of the current user of the current session + * (without using JAAS). All methods of this class require that a {@link VaadinRequest} is + * bound to the current thread. * * @see VaadinService#getCurrentRequest() */ public final class CurrentUser { - /** The attribute key used to store the username in the session. */ - public static final String CURRENT_USER_SESSION_ATTRIBUTE_KEY = - CurrentUser.class.getCanonicalName(); + /** The attribute key used to store the username in the session. */ + public static final String CURRENT_USER_SESSION_ATTRIBUTE_KEY = CurrentUser.class.getCanonicalName(); - private CurrentUser() {} + private CurrentUser() { + } - /** - * Returns the name of the current user stored in the current session, or an empty string if no - * user name is stored. - * - * @throws IllegalStateException if the current session cannot be accessed. - */ - public static String get() { - String currentUser = - (String) - getCurrentRequest() - .getWrappedSession() - .getAttribute(CURRENT_USER_SESSION_ATTRIBUTE_KEY); - if (currentUser == null) { - return ""; - } else { - return currentUser; - } - } + /** + * Returns the name of the current user stored in the current session, or an empty + * string if no user name is stored. + * @throws IllegalStateException if the current session cannot be accessed. + */ + public static String get() { + String currentUser = (String) getCurrentRequest().getWrappedSession() + .getAttribute(CURRENT_USER_SESSION_ATTRIBUTE_KEY); + if (currentUser == null) { + return ""; + } + else { + return currentUser; + } + } - /** - * Sets the name of the current user and stores it in the current session. Using a {@code null} - * username will remove the username from the session. - * - * @throws IllegalStateException if the current session cannot be accessed. - */ - public static void set(String currentUser) { - if (currentUser == null) { - getCurrentRequest().getWrappedSession().removeAttribute(CURRENT_USER_SESSION_ATTRIBUTE_KEY); - } else { - getCurrentRequest() - .getWrappedSession() - .setAttribute(CURRENT_USER_SESSION_ATTRIBUTE_KEY, currentUser); - } - } + /** + * Sets the name of the current user and stores it in the current session. Using a + * {@code null} username will remove the username from the session. + * @throws IllegalStateException if the current session cannot be accessed. + */ + public static void set(String currentUser) { + if (currentUser == null) { + getCurrentRequest().getWrappedSession().removeAttribute(CURRENT_USER_SESSION_ATTRIBUTE_KEY); + } + else { + getCurrentRequest().getWrappedSession().setAttribute(CURRENT_USER_SESSION_ATTRIBUTE_KEY, currentUser); + } + } + + private static VaadinRequest getCurrentRequest() { + VaadinRequest request = VaadinService.getCurrentRequest(); + if (request == null) { + throw new IllegalStateException("No request bound to current thread."); + } + return request; + } - private static VaadinRequest getCurrentRequest() { - VaadinRequest request = VaadinService.getCurrentRequest(); - if (request == null) { - throw new IllegalStateException("No request bound to current thread."); - } - return request; - } } diff --git a/src/main/java/org/karnak/frontend/authentication/LoginScreen.java b/src/main/java/org/karnak/frontend/authentication/LoginScreen.java index 7f0f79dd8..8fea9630e 100644 --- a/src/main/java/org/karnak/frontend/authentication/LoginScreen.java +++ b/src/main/java/org/karnak/frontend/authentication/LoginScreen.java @@ -39,121 +39,115 @@ @SuppressWarnings("serial") public class LoginScreen extends FlexLayout implements BeforeEnterObserver { - // View route - public static final String ROUTE = "login"; - - // Theme - private final String THEME_COLOR_KEY = "theme-variant"; - - // Login form - private final LoginForm loginForm; - - // Authentication manager - private final AuthenticationManager authenticationManager; - - // Request cache - private final RequestCache requestCache; - - @Autowired - public LoginScreen(AuthenticationManager authenticationManager, RequestCache requestCache) { - this.loginForm = new LoginForm(); - this.authenticationManager = authenticationManager; - this.requestCache = requestCache; - buildUI(); - } - - @Override - public void beforeEnter(BeforeEnterEvent beforeEnterEvent) { - // inform the user about an authentication error - if (beforeEnterEvent.getLocation().getQueryParameters().getParameters().containsKey("error")) { - loginForm.setError(true); - } - } - - /** Build User Interface */ - private void buildUI() { - setSizeFull(); - setClassName("login-screen"); - - // read local storage theme - UI.getCurrent() - .getPage() - .executeJs("return localStorage.getItem($0)", THEME_COLOR_KEY) - .then( - String.class, - string -> { - final String themeColor = string; - if ((string != null) && (string.equals(Lumo.DARK) || string.equals(Lumo.LIGHT))) { - UI.getCurrent().getElement().setAttribute("theme", themeColor); - UI.getCurrent() - .getPage() - .executeJs("localStorage.setItem($0, $1)", THEME_COLOR_KEY, themeColor); - } - }); - - // Build component - add(buildLoginMainComponent()); - - // It's ugly but it works. @see - // https://github.com/vaadin/vaadin-login-flow/issues/53 - UI.getCurrent() - .getPage() - .executeJavaScript("document.getElementById(\"vaadinLoginUsername\").focus();"); - } - - /** - * Build login component - * - * @return the built component - */ - private Component buildLoginMainComponent() { - - // sets the LoginForm action to "login" in order to post the login form to Spring Security - loginForm.setAction("login"); - - // deactivate forgot password button - loginForm.setForgotPasswordButtonVisible(false); - - // Listener on login form - loginForm.addLoginListener(this::login); - - // layout to center login form when there is sufficient screen space - VerticalLayout loginInformation = new VerticalLayout(); - loginInformation.setJustifyContentMode(JustifyContentMode.CENTER); - loginInformation.setAlignItems(Alignment.CENTER); - LogoKarnak logoKarnak = new LogoKarnak("KARNAK", "225px"); - loginInformation.add(logoKarnak); - loginInformation.add(new H1("KARNAK")); - loginInformation.add(loginForm); - - return loginInformation; - } - - /** - * Manage event on login form submit - * - * @param event Login Event - */ - private void login(LoginForm.LoginEvent event) { - try { - // try to authenticate with given credentials, - // should always return not null or throw an {@link AuthenticationException} - final Authentication authentication = - authenticationManager.authenticate( - new UsernamePasswordAuthenticationToken(event.getUsername(), event.getPassword())); - - // if the user is admin - if (authentication.getAuthorities().stream() - .anyMatch(ga -> Objects.equals(ga.getAuthority(), SecurityRole.ADMIN_ROLE.getRole()))) { - - // if authentication was successful and user is admin, - // we will update the security context and redirect to the page requested first - SecurityContextHolder.getContext().setAuthentication(authentication); - UI.getCurrent().navigate(requestCache.resolveRedirectUrl()); - } - } catch (AuthenticationException ex) { // - // show default error message - loginForm.setError(true); - } - } + // View route + public static final String ROUTE = "login"; + + // Theme + private final String THEME_COLOR_KEY = "theme-variant"; + + // Login form + private final LoginForm loginForm; + + // Authentication manager + private final AuthenticationManager authenticationManager; + + // Request cache + private final RequestCache requestCache; + + @Autowired + public LoginScreen(AuthenticationManager authenticationManager, RequestCache requestCache) { + this.loginForm = new LoginForm(); + this.authenticationManager = authenticationManager; + this.requestCache = requestCache; + buildUI(); + } + + @Override + public void beforeEnter(BeforeEnterEvent beforeEnterEvent) { + // inform the user about an authentication error + if (beforeEnterEvent.getLocation().getQueryParameters().getParameters().containsKey("error")) { + loginForm.setError(true); + } + } + + /** Build User Interface */ + private void buildUI() { + setSizeFull(); + setClassName("login-screen"); + + // read local storage theme + UI.getCurrent().getPage().executeJs("return localStorage.getItem($0)", THEME_COLOR_KEY).then(String.class, + string -> { + final String themeColor = string; + if ((string != null) && (string.equals(Lumo.DARK) || string.equals(Lumo.LIGHT))) { + UI.getCurrent().getElement().setAttribute("theme", themeColor); + UI.getCurrent().getPage().executeJs("localStorage.setItem($0, $1)", THEME_COLOR_KEY, + themeColor); + } + }); + + // Build component + add(buildLoginMainComponent()); + + // It's ugly but it works. @see + // https://github.com/vaadin/vaadin-login-flow/issues/53 + UI.getCurrent().getPage().executeJavaScript("document.getElementById(\"vaadinLoginUsername\").focus();"); + } + + /** + * Build login component + * @return the built component + */ + private Component buildLoginMainComponent() { + + // sets the LoginForm action to "login" in order to post the login form to Spring + // Security + loginForm.setAction("login"); + + // deactivate forgot password button + loginForm.setForgotPasswordButtonVisible(false); + + // Listener on login form + loginForm.addLoginListener(this::login); + + // layout to center login form when there is sufficient screen space + VerticalLayout loginInformation = new VerticalLayout(); + loginInformation.setJustifyContentMode(JustifyContentMode.CENTER); + loginInformation.setAlignItems(Alignment.CENTER); + LogoKarnak logoKarnak = new LogoKarnak("KARNAK", "225px"); + loginInformation.add(logoKarnak); + loginInformation.add(new H1("KARNAK")); + loginInformation.add(loginForm); + + return loginInformation; + } + + /** + * Manage event on login form submit + * @param event Login Event + */ + private void login(LoginForm.LoginEvent event) { + try { + // try to authenticate with given credentials, + // should always return not null or throw an {@link AuthenticationException} + final Authentication authentication = authenticationManager + .authenticate(new UsernamePasswordAuthenticationToken(event.getUsername(), event.getPassword())); + + // if the user is admin + if (authentication.getAuthorities().stream() + .anyMatch(ga -> Objects.equals(ga.getAuthority(), SecurityRole.ADMIN_ROLE.getRole()))) { + + // if authentication was successful and user is admin, + // we will update the security context and redirect to the page requested + // first + SecurityContextHolder.getContext().setAuthentication(authentication); + UI.getCurrent().navigate(requestCache.resolveRedirectUrl()); + } + } + catch (AuthenticationException ex) { // + // show default error message + loginForm.setError(true); + } + } + } diff --git a/src/main/java/org/karnak/frontend/authentication/NotAuthorizedScreen.java b/src/main/java/org/karnak/frontend/authentication/NotAuthorizedScreen.java index 1ca6ee19e..fa44e2e22 100644 --- a/src/main/java/org/karnak/frontend/authentication/NotAuthorizedScreen.java +++ b/src/main/java/org/karnak/frontend/authentication/NotAuthorizedScreen.java @@ -32,65 +32,60 @@ @SuppressWarnings("serial") public class NotAuthorizedScreen extends FlexLayout { - // View route - public static final String ROUTE = "not-authorized"; + // View route + public static final String ROUTE = "not-authorized"; - // Theme - private final String THEME_COLOR_KEY = "theme-variant"; + // Theme + private final String THEME_COLOR_KEY = "theme-variant"; - @Autowired - public NotAuthorizedScreen() { - buildUI(); - } + @Autowired + public NotAuthorizedScreen() { + buildUI(); + } - /** Build User Interface */ - private void buildUI() { - setSizeFull(); - setClassName("not-authorized-screen"); + /** Build User Interface */ + private void buildUI() { + setSizeFull(); + setClassName("not-authorized-screen"); - // read local storage theme - UI.getCurrent() - .getPage() - .executeJs("return localStorage.getItem($0)", THEME_COLOR_KEY) - .then( - String.class, - string -> { - final String themeColor = string; - if ((string != null) && (string.equals(Lumo.DARK) || string.equals(Lumo.LIGHT))) { - UI.getCurrent().getElement().setAttribute("theme", themeColor); - UI.getCurrent() - .getPage() - .executeJs("localStorage.setItem($0, $1)", THEME_COLOR_KEY, themeColor); - } - }); + // read local storage theme + UI.getCurrent().getPage().executeJs("return localStorage.getItem($0)", THEME_COLOR_KEY).then(String.class, + string -> { + final String themeColor = string; + if ((string != null) && (string.equals(Lumo.DARK) || string.equals(Lumo.LIGHT))) { + UI.getCurrent().getElement().setAttribute("theme", themeColor); + UI.getCurrent().getPage().executeJs("localStorage.setItem($0, $1)", THEME_COLOR_KEY, + themeColor); + } + }); - // Build component - add(buildNotAuthorizedComponent()); - } + // Build component + add(buildNotAuthorizedComponent()); + } - /** - * Build not authorized component - * - * @return the built component - */ - private Component buildNotAuthorizedComponent() { + /** + * Build not authorized component + * @return the built component + */ + private Component buildNotAuthorizedComponent() { - // layout to center login form when there is sufficient screen space - VerticalLayout notAuthorizedLayout = new VerticalLayout(); - notAuthorizedLayout.setJustifyContentMode(JustifyContentMode.CENTER); - notAuthorizedLayout.setAlignItems(Alignment.CENTER); - LogoKarnak logoKarnak = new LogoKarnak("KARNAK", "225px"); - notAuthorizedLayout.add(logoKarnak); - notAuthorizedLayout.add(new H1("KARNAK")); - notAuthorizedLayout.add(new H1("Not Authorized")); + // layout to center login form when there is sufficient screen space + VerticalLayout notAuthorizedLayout = new VerticalLayout(); + notAuthorizedLayout.setJustifyContentMode(JustifyContentMode.CENTER); + notAuthorizedLayout.setAlignItems(Alignment.CENTER); + LogoKarnak logoKarnak = new LogoKarnak("KARNAK", "225px"); + notAuthorizedLayout.add(logoKarnak); + notAuthorizedLayout.add(new H1("KARNAK")); + notAuthorizedLayout.add(new H1("Not Authorized")); - // logout button - Button logoutButton = new Button("Logout", VaadinIcon.SIGN_OUT.create()); - logoutButton.addClickListener(event -> SecurityUtil.signOut()); - logoutButton.addThemeVariants(ButtonVariant.LUMO_ERROR); - logoutButton.addThemeVariants(ButtonVariant.LUMO_LARGE); - notAuthorizedLayout.add(logoutButton); + // logout button + Button logoutButton = new Button("Logout", VaadinIcon.SIGN_OUT.create()); + logoutButton.addClickListener(event -> SecurityUtil.signOut()); + logoutButton.addThemeVariants(ButtonVariant.LUMO_ERROR); + logoutButton.addThemeVariants(ButtonVariant.LUMO_LARGE); + notAuthorizedLayout.add(logoutButton); + + return notAuthorizedLayout; + } - return notAuthorizedLayout; - } } diff --git a/src/main/java/org/karnak/frontend/component/AbstractDialog.java b/src/main/java/org/karnak/frontend/component/AbstractDialog.java index b1483daa4..6f866e7bf 100644 --- a/src/main/java/org/karnak/frontend/component/AbstractDialog.java +++ b/src/main/java/org/karnak/frontend/component/AbstractDialog.java @@ -17,22 +17,24 @@ public abstract class AbstractDialog extends Composite { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - protected VerticalLayout mainLayout; - private MessageBox messageBox; + protected VerticalLayout mainLayout; - protected abstract void createMainLayout(); + private MessageBox messageBox; - public void displayMessage(Message message) { - removeMessage(); - messageBox = new MessageBox(message, MessageType.STATIC_MESSAGE); - mainLayout.addComponentAtIndex(1, messageBox); - } + protected abstract void createMainLayout(); + + public void displayMessage(Message message) { + removeMessage(); + messageBox = new MessageBox(message, MessageType.STATIC_MESSAGE); + mainLayout.addComponentAtIndex(1, messageBox); + } + + public void removeMessage() { + if (messageBox != null) { + mainLayout.remove(messageBox); + } + } - public void removeMessage() { - if (messageBox != null) { - mainLayout.remove(messageBox); - } - } } diff --git a/src/main/java/org/karnak/frontend/component/BoxShadowComponent.java b/src/main/java/org/karnak/frontend/component/BoxShadowComponent.java index 52d3c2204..2fd60ab15 100644 --- a/src/main/java/org/karnak/frontend/component/BoxShadowComponent.java +++ b/src/main/java/org/karnak/frontend/component/BoxShadowComponent.java @@ -14,10 +14,11 @@ public class BoxShadowComponent extends Div { - public BoxShadowComponent(Component... component) { - getElement().getStyle().set("box-shadow", "var(--lumo-box-shadow-s)"); - getElement().getStyle().set("border-radius", "var(--lumo-border-radius-m)"); - getElement().getStyle().set("background-color", "hsla(245, 100%, 100%, 0.03)"); - add(component); - } + public BoxShadowComponent(Component... component) { + getElement().getStyle().set("box-shadow", "var(--lumo-box-shadow-s)"); + getElement().getStyle().set("border-radius", "var(--lumo-border-radius-m)"); + getElement().getStyle().set("background-color", "hsla(245, 100%, 100%, 0.03)"); + add(component); + } + } diff --git a/src/main/java/org/karnak/frontend/component/ConfirmDialog.java b/src/main/java/org/karnak/frontend/component/ConfirmDialog.java index 56f7706d7..10b4ad0eb 100644 --- a/src/main/java/org/karnak/frontend/component/ConfirmDialog.java +++ b/src/main/java/org/karnak/frontend/component/ConfirmDialog.java @@ -25,153 +25,153 @@ public class ConfirmDialog extends Composite { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - // UI COMPONENTS - private Dialog dialog; + // UI COMPONENTS + private Dialog dialog; - private VerticalLayout mainLayout; + private VerticalLayout mainLayout; - private HorizontalLayout headerLayout; - private Span titleText; - private Div messageLayout; - private HorizontalLayout buttonsLayout; - private Button yesBtn; - private Button noBtn; + private HorizontalLayout headerLayout; - // DATA - private final String messageText; + private Span titleText; - public ConfirmDialog(String messageText) { - this.messageText = messageText; + private Div messageLayout; - init(); + private HorizontalLayout buttonsLayout; - createMainLayout(); - - dialog.add(mainLayout); - } + private Button yesBtn; - public void open() { - dialog.open(); - } + private Button noBtn; - // LISTENERS - public Registration addConfirmationListener(ComponentEventListener listener) { - return addListener(ConfirmationEvent.class, listener); - } - - private void init() { - dialog = getContent(); - dialog.setId("confirm-dialog"); - dialog.setCloseOnEsc(false); - dialog.setCloseOnOutsideClick(false); - } + // DATA + private final String messageText; + + public ConfirmDialog(String messageText) { + this.messageText = messageText; + + init(); + + createMainLayout(); + + dialog.add(mainLayout); + } + + public void open() { + dialog.open(); + } + + // LISTENERS + public Registration addConfirmationListener(ComponentEventListener listener) { + return addListener(ConfirmationEvent.class, listener); + } + + private void init() { + dialog = getContent(); + dialog.setId("confirm-dialog"); + dialog.setCloseOnEsc(false); + dialog.setCloseOnOutsideClick(false); + } + + private void createMainLayout() { + mainLayout = new VerticalLayout(); + mainLayout.setSizeFull(); + mainLayout.addClassName("dialog-container"); + + createHeaderLayout(); + createMessageLayout(); + createButtonsLayout(); + + mainLayout.add(headerLayout, messageLayout, buttonsLayout); + } + + private void createHeaderLayout() { + headerLayout = new HorizontalLayout(); + headerLayout.setWidthFull(); + headerLayout.addClassName("dialog-title"); + headerLayout.setAlignItems(Alignment.BASELINE); + + createTitleText(); + + headerLayout.add(titleText); + } + + private void createTitleText() { + titleText = new Span("Confirmation"); + titleText.getStyle().set("font-size", "24px"); + titleText.getStyle().set("font-weight", "400"); + } + + private void createMessageLayout() { + messageLayout = new Div(); + messageLayout.addClassName("dialog-content"); + + messageLayout.add(messageText); + } + + private void createButtonsLayout() { + buttonsLayout = new HorizontalLayout(); + buttonsLayout.setWidthFull(); + buttonsLayout.addClassName("dialog-buttons"); + + createNoBtn(); + createYesBtn(); + + buttonsLayout.add(noBtn, yesBtn); + + noBtn.getElement().getStyle().set("margin-left", "auto"); // https://vaadin.com/forum/thread/17198105/button-alignment-in-horizontal-layout + } + + @SuppressWarnings("serial") + private void createYesBtn() { + yesBtn = new Button(); + yesBtn.addClassName("stroked-button"); + yesBtn.addClassName("primary"); + yesBtn.setText("Oui"); + yesBtn.setWidth("90px"); + + yesBtn.focus(); + + yesBtn.addClickListener(new ComponentEventListener>() { + + @Override + public void onComponentEvent(ClickEvent