Skip to content

Commit f184cdb

Browse files
authored
Merge pull request dcm4che#1511 from jknocek/lenient-person-name-set
Add lenient option on `PersonName.set(Group g, String s)`
2 parents 3f69406 + b0a21a3 commit f184cdb

2 files changed

Lines changed: 101 additions & 31 deletions

File tree

dcm4che-core/src/main/java/org/dcm4che3/data/PersonName.java

Lines changed: 49 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,11 @@ public class PersonName {
5555

5656
public enum Component {
5757
FamilyName, GivenName, MiddleName, NamePrefix, NameSuffix
58-
};
58+
}
5959

6060
public enum Group {
6161
Alphabetic, Ideographic, Phonetic
62-
};
62+
}
6363

6464
private final String[] fields = new String[15];
6565

@@ -74,60 +74,78 @@ public PersonName(String s, boolean lenient) {
7474
parse(s, lenient);
7575
}
7676

77+
/**
78+
* Set all components of a component group from encoded component group value.
79+
*
80+
* @param g component group
81+
* @param s encoded component group value
82+
*/
83+
public void set(Group g, String s) {
84+
set(g, s, false);
85+
}
86+
87+
/**
88+
* Sets all components of a specified component group based on an encoded component group value.
89+
*
90+
* @param g the component group to be set
91+
* @param s the encoded component group value, must not contain '=' and must have at most 5 components when split by '^'
92+
* @param lenient whether the operation should be lenient in handling the input value
93+
* @throws IllegalArgumentException if the input string contains '=' or has more than 5 components when split by '^'
94+
*/
95+
public void set(Group g, String s, boolean lenient) {
96+
if (s.indexOf('=') >= 0)
97+
throw new IllegalArgumentException(s);
98+
99+
parse(g, s, lenient);
100+
}
101+
77102
private void parse(String s, boolean lenient) {
78-
int gindex = 0;
103+
parseInternal(null, s, lenient);
104+
}
105+
106+
private void parse(Group g, String s, boolean lenient) {
107+
parseInternal(g, s, lenient);
108+
}
109+
110+
private void parseInternal(Group g, String s, boolean lenient) {
111+
int gindex = (g == null) ? 0 : g.ordinal();
79112
int cindex = 0;
80-
StringTokenizer stk = new StringTokenizer(s, "^=", true);
113+
StringTokenizer stk = new StringTokenizer(s, (g == null) ? "^=" : "^", true);
81114
while (stk.hasMoreTokens()) {
82115
String tk = stk.nextToken();
83116
switch (tk.charAt(0)) {
84117
case '=':
85-
if (++gindex > 2)
118+
if (g != null) {
119+
throw new IllegalArgumentException("Invalid '=' token in group parsing: " + s);
120+
}
121+
if (++gindex > 2) {
86122
if (lenient) {
87-
LOG.info(
88-
"illegal PN: {} - truncate illegal component group(s)", s);
123+
LOG.info("illegal PN: {} - truncate illegal component group(s)", s);
89124
return;
90-
} else
125+
} else {
91126
throw new IllegalArgumentException(s);
127+
}
128+
}
92129
cindex = 0;
93130
break;
94131
case '^':
95132
++cindex;
96133
break;
97134
default:
98-
if (cindex <= 4)
135+
if (cindex <= 4) {
99136
set(gindex, cindex, tk);
100-
else if (lenient) {
137+
} else if (lenient) {
101138
if ((tk = trim(tk)) != null) {
102139
LOG.info("illegal PN: {} - subsumes {}th component in suffix", s, cindex + 1);
103140
set(gindex, 4, StringUtils.maskNull(get(gindex, 4), "") + ' ' + tk);
104141
}
105-
} else
142+
} else {
106143
throw new IllegalArgumentException(s);
144+
}
107145
}
108146
}
109147
}
110148

111-
/**
112-
* Set all components of a component group from encoded component group value.
113-
*
114-
* @param g component group
115-
* @param s encoded component group value
116-
*/
117-
public void set(Group g, String s) {
118-
int gindex = g.ordinal();
119-
if (s.indexOf('=') >= 0)
120-
throw new IllegalArgumentException(s);
121-
122-
String[] ss = StringUtils.split(s, '^');
123-
if (ss.length > 5)
124-
throw new IllegalArgumentException(s);
125-
126-
for (int cindex = 0; cindex < 5; cindex++) {
127-
fields[gindex * 5 + cindex] = cindex < ss.length ? trim(ss[cindex]) : null;
128-
}
129-
}
130-
131149
public String toString() {
132150
int totLen = 0;
133151
Group lastGroup = Group.Alphabetic;

dcm4che-core/src/test/java/org/dcm4che3/data/PersonNameTest.java

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,4 +118,56 @@ public void testToString2() {
118118
assertEquals("^^^^", pn.toString(PersonName.Group.Phonetic, false));
119119
}
120120

121+
@Test
122+
public void testLenientDisabled() {
123+
String aName = "Fry^Phillip^J^p^s^extra";
124+
String iName = "フライ^フィリップ^ジェイ^ピー^エス^エクストラ";
125+
String pName = "Furai^Firippu^Jei^Pi^Esu^Ekusutora";
126+
127+
String fullName = aName+ "=" + iName + "=" + pName;
128+
129+
assertThrows(IllegalArgumentException.class, () -> new PersonName(fullName));
130+
assertThrows(IllegalArgumentException.class, () -> {
131+
PersonName set_pn = new PersonName();
132+
set_pn.set(PersonName.Group.Alphabetic, aName);
133+
set_pn.set(PersonName.Group.Ideographic, iName);
134+
set_pn.set(PersonName.Group.Phonetic, pName);
135+
});
136+
}
137+
138+
@Test
139+
public void testLenientEnabled() {
140+
String aName = "Fry^Phillip^J^p^s^extra";
141+
String iName = "フライ^フィリップ^ジェイ^ピー^エス^エクストラ";
142+
String pName = "Furai^Firippu^Jei^Pi^Esu^Ekusutora";
143+
144+
String fullName = aName+ "=" + iName + "=" + pName;
145+
146+
PersonName cons_pn = new PersonName(fullName, true);
147+
PersonName set_pn = new PersonName();
148+
set_pn.set(PersonName.Group.Alphabetic, aName, true);
149+
set_pn.set(PersonName.Group.Ideographic, iName, true);
150+
set_pn.set(PersonName.Group.Phonetic, pName, true);
151+
152+
assertEquals(cons_pn, set_pn);
153+
154+
assertEquals("Fry", cons_pn.get(PersonName.Group.Alphabetic, PersonName.Component.FamilyName));
155+
assertEquals("Phillip", cons_pn.get(PersonName.Group.Alphabetic, PersonName.Component.GivenName));
156+
assertEquals("J", cons_pn.get(PersonName.Group.Alphabetic, PersonName.Component.MiddleName));
157+
assertEquals("p", cons_pn.get(PersonName.Group.Alphabetic, PersonName.Component.NamePrefix));
158+
assertEquals("s extra", cons_pn.get(PersonName.Group.Alphabetic, PersonName.Component.NameSuffix));
159+
160+
assertEquals("フライ", cons_pn.get(PersonName.Group.Ideographic, PersonName.Component.FamilyName));
161+
assertEquals("フィリップ", cons_pn.get(PersonName.Group.Ideographic, PersonName.Component.GivenName));
162+
assertEquals("ジェイ", cons_pn.get(PersonName.Group.Ideographic, PersonName.Component.MiddleName));
163+
assertEquals("ピー", cons_pn.get(PersonName.Group.Ideographic, PersonName.Component.NamePrefix));
164+
assertEquals("エス エクストラ", cons_pn.get(PersonName.Group.Ideographic, PersonName.Component.NameSuffix));
165+
166+
assertEquals("Furai", cons_pn.get(PersonName.Group.Phonetic, PersonName.Component.FamilyName));
167+
assertEquals("Firippu", cons_pn.get(PersonName.Group.Phonetic, PersonName.Component.GivenName));
168+
assertEquals("Jei", cons_pn.get(PersonName.Group.Phonetic, PersonName.Component.MiddleName));
169+
assertEquals("Pi", cons_pn.get(PersonName.Group.Phonetic, PersonName.Component.NamePrefix));
170+
assertEquals("Esu Ekusutora", cons_pn.get(PersonName.Group.Phonetic, PersonName.Component.NameSuffix));
171+
}
172+
121173
}

0 commit comments

Comments
 (0)