From 858f364b68e1f09a5fbf0792f98def060110eb50 Mon Sep 17 00:00:00 2001
From: Nirostar <36939232+Nirostar@users.noreply.github.com>
Date: Wed, 28 Sep 2022 14:46:09 +0200
Subject: [PATCH 1/5] Set version number to next SNAPSHOT
---
README.MD | 6 +++---
gradle.properties | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/README.MD b/README.MD
index e76aa51..42eccc0 100644
--- a/README.MD
+++ b/README.MD
@@ -19,7 +19,7 @@ repositories {
```groovy
dependencies {
- implementation 'org.dcm4che:dcm4che-typeddicom:0.4.2'
+ implementation 'org.dcm4che:dcm4che-typeddicom:0.4.3-SNAPSHOT'
}
```
@@ -35,7 +35,7 @@ repositories {
```kotlin
dependencies {
- implementation("org.dcm4che:dcm4che-typeddicom:0.4.2")
+ implementation("org.dcm4che:dcm4che-typeddicom:0.4.3-SNAPSHOT")
}
```
@@ -54,7 +54,7 @@ dependencies {
org.dcm4che
dcm4che-typeddicom
- 0.4.2
+ 0.4.3-SNAPSHOT
```
diff --git a/gradle.properties b/gradle.properties
index 7805828..70f4047 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,3 +1,3 @@
-version=0.4.2
+version=0.4.3-SNAPSHOT
org.gradle.jvmargs=-Xmx4096m
org.gradle.caching=true
From 82affb13e90d66ecc028892ebaf55e3b8b8ca6b9 Mon Sep 17 00:00:00 2001
From: Nirostar <36939232+Nirostar@users.noreply.github.com>
Date: Thu, 29 Sep 2022 08:55:54 +0200
Subject: [PATCH 2/5] Add Builder converter method
---
.../src/main/java/org/dcm4che/typeddicom/Builder.java | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/dcm4che-typeddicom-lib/src/main/java/org/dcm4che/typeddicom/Builder.java b/dcm4che-typeddicom-lib/src/main/java/org/dcm4che/typeddicom/Builder.java
index ff930ca..307d3ba 100644
--- a/dcm4che-typeddicom-lib/src/main/java/org/dcm4che/typeddicom/Builder.java
+++ b/dcm4che-typeddicom-lib/src/main/java/org/dcm4che/typeddicom/Builder.java
@@ -19,4 +19,8 @@ default SELF setSequence(String privateCreator, int tag, Builder, ?>... itemBu
}
return (SELF) this;
}
+
+ default B as(Class builderClass) {
+ return AttributesWrapper.wrap(this.getAttributes(), builderClass);
+ }
}
From f84bfb6a39618447978d83f61fd066175555cbad Mon Sep 17 00:00:00 2001
From: Nirostar <36939232+Nirostar@users.noreply.github.com>
Date: Wed, 30 Nov 2022 18:18:47 +0100
Subject: [PATCH 3/5] Add Private Creator to Sequences
---
.../typeddicom/DataElementWrapper.java | 14 +++++------
.../dcm4che/typeddicom/SequenceWrapper.java | 6 +++++
.../templates/DataElement.java.mustache | 24 +++++++++++++------
3 files changed, 29 insertions(+), 15 deletions(-)
diff --git a/dcm4che-typeddicom-lib/src/main/java/org/dcm4che/typeddicom/DataElementWrapper.java b/dcm4che-typeddicom-lib/src/main/java/org/dcm4che/typeddicom/DataElementWrapper.java
index fb90166..4cb7844 100644
--- a/dcm4che-typeddicom-lib/src/main/java/org/dcm4che/typeddicom/DataElementWrapper.java
+++ b/dcm4che-typeddicom-lib/src/main/java/org/dcm4che/typeddicom/DataElementWrapper.java
@@ -13,20 +13,18 @@ public interface DataElementWrapper extends AttributesWrapper {
*/
VR getValueRepresentation();
+ /**
+ * @return The DICOM
+ * Private Creator of the wrapped DICOM attributes. null if not private
+ */
+ String getPrivateCreator();
+
/**
* @return The DICOM
* Tag of the wrapped DICOM attributes.
*/
int getTag();
- /**
- * @return The DICOM
- * Private Creator of the wrapped DICOM attributes.
- */
- default String getPrivateCreator() {
- return null;
- }
-
Object getValue();
boolean exists();
diff --git a/dcm4che-typeddicom-lib/src/main/java/org/dcm4che/typeddicom/SequenceWrapper.java b/dcm4che-typeddicom-lib/src/main/java/org/dcm4che/typeddicom/SequenceWrapper.java
index f9810d7..6e2b6cc 100644
--- a/dcm4che-typeddicom-lib/src/main/java/org/dcm4che/typeddicom/SequenceWrapper.java
+++ b/dcm4che-typeddicom-lib/src/main/java/org/dcm4che/typeddicom/SequenceWrapper.java
@@ -34,6 +34,12 @@ public VR getValueRepresentation() {
return VALUE_REPRESENTATION;
}
+ /**
+ * @return The DICOM
+ * Private Creator of the wrapped DICOM attributes. null if not private
+ */
+ public abstract String getPrivateCreator();
+
/**
* @return The DICOM
* Tag of the wrapped DICOM sequence.
diff --git a/dcm4che-typeddicom-lib/src/main/resources/templates/DataElement.java.mustache b/dcm4che-typeddicom-lib/src/main/resources/templates/DataElement.java.mustache
index ff0cbf6..f716723 100644
--- a/dcm4che-typeddicom-lib/src/main/resources/templates/DataElement.java.mustache
+++ b/dcm4che-typeddicom-lib/src/main/resources/templates/DataElement.java.mustache
@@ -25,6 +25,11 @@ import java.util.Arrays;
@Deprecated
{{/retired}}
public class {{keyword}} extends {{#sequence}}SequenceWrapper<{{keyword}}, {{keyword}}.Item>{{/sequence}}{{^sequence}}AbstractDataElementWrapper implements {{valueRepresentationWrapper}}{{/sequence}} {
+ /**
+ * The Private Creator
+ * associated with this class.
+ */
+ public static final String PRIVATE_CREATOR = null;
/**
* The DICOM Tag
* associated with this class.
@@ -70,6 +75,11 @@ public class {{keyword}} extends {{#sequence}}SequenceWrapper<{{keyword}}, {{key
}
{{/sequence}}
+ @Override
+ public String getPrivateCreator() {
+ return PRIVATE_CREATOR;
+ }
+
@Override
public int getTag() {
return TAG;
@@ -150,7 +160,7 @@ public class {{keyword}} extends {{#sequence}}SequenceWrapper<{{keyword}}, {{key
/**
* @return a {@link Builder} to create {{name}} Items with a fluent API.
*/
- public static Builder builder() {
+ static Builder builder() {
return new Builder();
}
@@ -159,7 +169,7 @@ public class {{keyword}} extends {{#sequence}}SequenceWrapper<{{keyword}}, {{key
*
* @return a {@link Builder} to create {{name}} Items with a fluent API. Instead of creating new Attributes it wraps the provided Attributes.
*/
- public static Builder builder(Attributes attributes) {
+ static Builder builder(Attributes attributes) {
return new Builder(attributes);
}
@@ -168,7 +178,7 @@ public class {{keyword}} extends {{#sequence}}SequenceWrapper<{{keyword}}, {{key
*/
default {{keyword}} get{{keyword}}() {
{{#sequence}}
- Sequence sequence = getAttributes().getSequence(TAG);
+ Sequence sequence = getAttributes().getSequence(PRIVATE_CREATOR, TAG);
if (sequence == null) {
return null;
}
@@ -186,7 +196,7 @@ public class {{keyword}} extends {{#sequence}}SequenceWrapper<{{keyword}}, {{key
* @param initialCapacity the initial capacity for the new {{name}}
*/
default {{keyword}} new{{keyword}}(int initialCapacity) {
- return new {{keyword}}(getAttributes().newSequence(TAG, initialCapacity));
+ return new {{keyword}}(getAttributes().newSequence(PRIVATE_CREATOR, TAG, initialCapacity));
}
/**
@@ -199,7 +209,7 @@ public class {{keyword}} extends {{#sequence}}SequenceWrapper<{{keyword}}, {{key
* initialCapacity
.
*/
default {{keyword}} ensure{{keyword}}(int initialCapacity) {
- return new {{keyword}}(getAttributes().ensureSequence(TAG, initialCapacity));
+ return new {{keyword}}(getAttributes().ensureSequence(PRIVATE_CREATOR, TAG, initialCapacity));
}
/**
@@ -217,14 +227,14 @@ public class {{keyword}} extends {{#sequence}}SequenceWrapper<{{keyword}}, {{key
* @return Whether it contains the {{name}} (see {@link {{keyword}}})
*/
default boolean contains{{keyword}}() {
- return getAttributes().contains(TAG);
+ return getAttributes().contains(PRIVATE_CREATOR, TAG);
}
/**
* Removes the {{name}} (see {@link {{keyword}}}
*/
default void remove{{keyword}}() {
- getAttributes().remove(TAG);
+ getAttributes().remove(PRIVATE_CREATOR, TAG);
}
class Builder extends AbstractAttributesWrapper implements org.dcm4che.typeddicom.Builder, {{keyword}}.Builder {
From 646ebc8d763d228fb97215ddace1c3d56cda28b7 Mon Sep 17 00:00:00 2001
From: Nirostar <36939232+Nirostar@users.noreply.github.com>
Date: Wed, 30 Nov 2022 19:30:04 +0100
Subject: [PATCH 4/5] Add support for functional group macros
---
.../typeddicom/DicomPart03Handler.java | 57 +++++++++++++------
1 file changed, 41 insertions(+), 16 deletions(-)
diff --git a/buildSrc/src/main/java/org/dcm4che/typeddicom/DicomPart03Handler.java b/buildSrc/src/main/java/org/dcm4che/typeddicom/DicomPart03Handler.java
index 8a4174d..7887e21 100644
--- a/buildSrc/src/main/java/org/dcm4che/typeddicom/DicomPart03Handler.java
+++ b/buildSrc/src/main/java/org/dcm4che/typeddicom/DicomPart03Handler.java
@@ -8,12 +8,14 @@
import org.xml.sax.SAXException;
import java.util.*;
+import java.util.stream.Collectors;
/**
* This class parses the 3th part of the DICOM Standard XML
* (http://dicom.nema.org/medical/dicom/current/source/docbook/part03/part03.xml)
*/
public class DicomPart03Handler extends MemorizeTablesDicomPartHandler {
+ private static final String FUNCTIONAL_GROUP_MACRO_REFERENCE = "FUNCTIONAL GROUP MACRO";
private final Set modules;
private final Map> dataElementMetaInfos;
private final Set iods;
@@ -211,10 +213,11 @@ private void handleEndOfAttributesTableRow() {
int currentSequenceDepth = sequenceDepth(name);
name = name.substring(currentSequenceDepth).trim();
TableEntry currentTableEntry;
- boolean validInclude = name.startsWith("Include") &&
+ boolean validStandardInclude = name.startsWith("Include") &&
lastReferenceInFirstColumn != null &&
lastReferenceInFirstColumn.startsWith("table_");
boolean validAttribute = columns.size() > 1 && columns.get(1).matches("\\([0-9A-F]{2}[0-9A-Fx]{2},[0-9A-F]{2}[0-9A-Fx]{2}\\)");
+ boolean validFunctionalGroupMacroInclude = name.startsWith("Include one or more Functional Group Macros");
if (columns.size() == 3 && validAttribute) {
currentTableEntry = new AttributeTableEntry(tableEntryHref, name, columns.get(1), columns.get(2));
} else if (columns.size() == 4 && validAttribute) {
@@ -225,10 +228,12 @@ private void handleEndOfAttributesTableRow() {
columns.get(2),
columns.get(3)
);
- } else if (columns.size() == 2 && validInclude) {
+ } else if (columns.size() == 2 && validStandardInclude) {
currentTableEntry = new MacroTableEntry(tableEntryHref, lastReferenceInFirstColumn, columns.get(1));
- } else if (columns.size() == 1 && validInclude) {
+ } else if (columns.size() == 1 && validStandardInclude) {
currentTableEntry = new MacroTableEntry(tableEntryHref, lastReferenceInFirstColumn);
+ } else if (validFunctionalGroupMacroInclude) {
+ currentTableEntry = new MacroTableEntry(tableEntryHref, FUNCTIONAL_GROUP_MACRO_REFERENCE);
} else {
System.out.println("Invalid Row: " + Arrays.toString(columns.toArray()));
return;
@@ -243,31 +248,32 @@ private String extractModuleReference(String html) {
if (html == null) {
return null;
}
- String moduleRef = html.replaceAll("(?s).*?.*$", "$1");
- return moduleRef;
+ return html.replaceAll("(?s).*?.*$", "$1");
}
private Iterable resolveMacrosRecursively(TableEntry tableEntry, Context context) {
if (tableEntry instanceof MacroTableEntry macroTableEntry) {
String tableId = macroTableEntry.getTableId();
- MacroTable macroTable = macroTables.get(tableId);
- if (macroTable == null) {
+ Set matchingMacroTables = getMatchingMacroTables(tableId);
+ if (matchingMacroTables.isEmpty()) {
System.out.println("Invalid macro key: " + tableId);
return Collections.emptyList();
}
MacroMetaInfo macroMetaInfo = macros.get(tableId);
if (macroMetaInfo == null) {
- macroMetaInfo = new MacroMetaInfo(macroTable.getTableId());
+ macroMetaInfo = new MacroMetaInfo(tableId);
macros.put(macroMetaInfo.getTableId(), macroMetaInfo);
}
- for (TableEntry macroSubEntry : macroTable.getTableEntries()) {
- ContextEntry newContextEntry = new ContextEntry(macroTable.getName(), macroTable.getHref());
- // Stop at recursive macros
- if (!context.getContext().contains(newContextEntry)) {
- macroMetaInfo.addDataElementMetaInfo(resolveMacrosRecursively(
- macroSubEntry,
- new Context(newContextEntry)
- ));
+ for (MacroTable macroTable : matchingMacroTables) {
+ for (TableEntry macroSubEntry : macroTable.getTableEntries()) {
+ ContextEntry newContextEntry = new ContextEntry(macroTable.getName(), macroTable.getHref());
+ // Stop at recursive macros
+ if (!context.getContext().contains(newContextEntry)) {
+ macroMetaInfo.addDataElementMetaInfo(resolveMacrosRecursively(
+ macroSubEntry,
+ new Context(newContextEntry)
+ ));
+ }
}
}
return macroMetaInfo.getSubDataElementMetaInfos();
@@ -303,6 +309,25 @@ private Iterable resolveMacrosRecursively(TableEntry tableE
}
return Collections.emptyList();
}
+
+ // Usually only one macro matches, but there is also the Functional Groups Macros which get combined to one special macro
+ private Set getMatchingMacroTables(String tableId) {
+ Set matchingMacroTables;
+ if (FUNCTIONAL_GROUP_MACRO_REFERENCE.equals(tableId)) {
+ matchingMacroTables = macroTables.entrySet().stream()
+ .filter(entry -> entry.getKey().startsWith("table_C.7.6.16"))
+ .map(Map.Entry::getValue)
+ .collect(Collectors.toSet());
+ } else {
+ MacroTable matchingMacroTable = macroTables.get(tableId);
+ if (matchingMacroTable == null) {
+ matchingMacroTables = Collections.emptySet();
+ } else {
+ matchingMacroTables = Collections.singleton(matchingMacroTable);
+ }
+ }
+ return matchingMacroTables;
+ }
private void removeHTMLTagsFromColumn(Integer i) {
if (i == null || i >= this.columns.size()) {
From d3ba908962fc18c740305d9333025f233241e3eb Mon Sep 17 00:00:00 2001
From: Nirostar <36939232+Nirostar@users.noreply.github.com>
Date: Thu, 1 Dec 2022 11:15:48 +0100
Subject: [PATCH 5/5] Set version number to release
---
README.MD | 6 +++---
gradle.properties | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/README.MD b/README.MD
index 42eccc0..ea607b3 100644
--- a/README.MD
+++ b/README.MD
@@ -19,7 +19,7 @@ repositories {
```groovy
dependencies {
- implementation 'org.dcm4che:dcm4che-typeddicom:0.4.3-SNAPSHOT'
+ implementation 'org.dcm4che:dcm4che-typeddicom:0.4.3'
}
```
@@ -35,7 +35,7 @@ repositories {
```kotlin
dependencies {
- implementation("org.dcm4che:dcm4che-typeddicom:0.4.3-SNAPSHOT")
+ implementation("org.dcm4che:dcm4che-typeddicom:0.4.3")
}
```
@@ -54,7 +54,7 @@ dependencies {
org.dcm4che
dcm4che-typeddicom
- 0.4.3-SNAPSHOT
+ 0.4.3
```
diff --git a/gradle.properties b/gradle.properties
index 70f4047..e549c34 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,3 +1,3 @@
-version=0.4.3-SNAPSHOT
+version=0.4.3
org.gradle.jvmargs=-Xmx4096m
org.gradle.caching=true