Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/Helper methods for personname.GroupInfo values in a veterinary context #180

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions pkg/personname/examples_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,3 +238,81 @@ func ExampleInfo_WithoutEmptyGroups_hasPhonetic() {
// ORIGINAL : Potter^Harry^^^=^^^^=hɛər.i^pɒ.tər^dʒeɪmz^^
// REFORMATTED: Potter^Harry^^^==hɛər.i^pɒ.tər^dʒeɪmz^^
}

func ExampleNewVeterinaryGroupInfo() {
// Create a new groupInfo in a veterinary context.
groupInfo := personname.NewVeterinaryGroupInfo(
"Potter", // responsibleParty
"Hedwig", // patientName
)

fmt.Println("DCM VETERINARY:", groupInfo.MustDCM())

// This is equivalent to:
groupInfo = personname.GroupInfo{
FamilyName: "Potter",
GivenName: "Hedwig",
TrailingNullLevel: personname.GroupNullLevelNone,
}

fmt.Println("DCM NORMAL :", groupInfo.MustDCM())

// Output:
// DCM VETERINARY: Potter^Hedwig
// DCM NORMAL : Potter^Hedwig
}

// ExampleGroupInfo_Veterinary shows how to use the Veterinary() method helpers on
// a GroupInfo value.
func ExampleGroupInfo_Veterinary() {
// Create a new groupInfo in a veterinary context.
groupInfo := personname.NewVeterinaryGroupInfo(
"Potter", // responsibleParty
"Hedwig", // patientName
)

fmt.Println("DCM VETERINARY :", groupInfo.MustDCM())
fmt.Println("RESPONSIBLE PARTY:", groupInfo.Veterinary().ResponsibleParty())
fmt.Println("PATIENT NAME :", groupInfo.Veterinary().PatientName())

// This is equivalent to:
groupInfo = personname.GroupInfo{
FamilyName: "Potter",
GivenName: "Hedwig",
TrailingNullLevel: personname.GroupNullLevelNone,
}

fmt.Println()
fmt.Println("DCM NORMAL :", groupInfo.MustDCM())
fmt.Println("FAMILY NAME:", groupInfo.FamilyName)
fmt.Println("GIVEN NAME:", groupInfo.GivenName)

// Out Veterinary() namespace also includes setter methods:
groupInfo.Veterinary().SetResponsibleParty("Weasley")
groupInfo.Veterinary().SetPatientName("Scabbers")

fmt.Println()
fmt.Println("DCM VETERINARY :", groupInfo.MustDCM())
fmt.Println("RESPONSIBLE PARTY:", groupInfo.Veterinary().ResponsibleParty())
fmt.Println("PATIENT NAME :", groupInfo.Veterinary().PatientName())

// Under the hood, we can see that all we have done is set the regular fields that
// are used to represent these values in a Veterinary Context:
fmt.Println("FAMILY NAME :", groupInfo.FamilyName)
fmt.Println("GIVEN NAME :", groupInfo.GivenName)

// Output:
// DCM VETERINARY : Potter^Hedwig
// RESPONSIBLE PARTY: Potter
// PATIENT NAME : Hedwig
//
// DCM NORMAL : Potter^Hedwig
// FAMILY NAME: Potter
// GIVEN NAME: Hedwig
//
// DCM VETERINARY : Weasley^Scabbers
// RESPONSIBLE PARTY: Weasley
// PATIENT NAME : Scabbers
// FAMILY NAME : Weasley
// GIVEN NAME : Scabbers
}
76 changes: 76 additions & 0 deletions pkg/personname/groupInfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,82 @@ func (group GroupInfo) IsEmpty() bool {
group.NameSuffix == ""
}

// Veterinary returns a read / write data access value that points to the calling
// GroupInfo value with helper methods specific to veterinary contexts.
//
// This helper value should not be passed around itself, but used in chained commands:
//
// petName := groupInfo.Veterinary().PatientName()
// groupInfo.Veterinary().SetPatientName(petName)
func (group *GroupInfo) Veterinary() VeterinaryInfo {
return VeterinaryInfo{groupInfo: group}
}

// VeterinaryInfo acts as a namespace for veterinary-specific methods on GroupInfo.
//
// VeterinaryInfo should not be extracted and used on it's own. It is included as a more
// explicit API for veterinary settings and should be invoked via chained calls:
//
// petName := groupInfo.Veterinary().PatientName()
// groupInfo.Veterinary().SetPatientName(petName)
type VeterinaryInfo struct {
groupInfo *GroupInfo
}

// ResponsibleParty returns the Responsible Party Family Name / Responsible
// Organization Name for the patient.
//
// ResponsibleParty simply returns GroupInfo.FamilyName, and is included a more explicit
// way of communicating you are getting this information in a Veterinary context.
func (vet VeterinaryInfo) ResponsibleParty() string {
return vet.groupInfo.FamilyName
}

// SetResponsibleParty sets the Responsible Party Family Name / Responsible
// organization name for the patient.
//
// SetResponsibleParty simply sets GroupInfo.FamilyName, and is included a more explicit
// way of communicating you are setting this information in a Veterinary context.
func (vet VeterinaryInfo) SetResponsibleParty(name string) {
vet.groupInfo.FamilyName = name
}

// PatientName is the full name of the Pet, Animal, etc.
//
// PatientName simply returns GroupInfo.GivenName, and is included a more explicit
// way of communicating you are getting this information in a Veterinary context.
func (vet VeterinaryInfo) PatientName() string {
return vet.groupInfo.GivenName
}

// SetPatientName sets the full name of the Pet, Animal, etc.
//
// SetPatientName simply sets GroupInfo.GivenName, and is included a more explicit
// way of communicating you are setting this information in a Veterinary context.
func (vet VeterinaryInfo) SetPatientName(name string) {
vet.groupInfo.GivenName = name
}

// NewVeterinaryGroupInfo is a helper function for creating new GroupInfo values in a
// veterinary context.
//
// Returns a GroupInfo value with GroupInfo.FamilyName set to responsibleParty,
// GroupInfo.GivenName set to patientName, and GroupInfo.TrailingNullLevel set to
// GroupNullLevelNone.
//
// From the dicom spec:
//
// For veterinary use, the first two of the five components in their order of
// occurrence are: responsible party family name or responsible organization name,
// patient name. The remaining components are not used and shall not be present.
func NewVeterinaryGroupInfo(responsibleParty, patientName string) GroupInfo {
return GroupInfo{
FamilyName: responsibleParty,
GivenName: patientName,
TrailingNullLevel: GroupNullLevelNone,
}
}

// groupFromValueString converts a string from a dicom element with a Value
// Representation of PN to a parsed Info struct.
func groupFromValueString(groupString string, group pnGroup) (GroupInfo, error) {
Expand Down
83 changes: 83 additions & 0 deletions pkg/personname/groupInfo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -442,3 +442,86 @@ func TestNewPersonNameFromDicom_Err(t *testing.T) {
t.Errorf("unexpected error text: %v", err.Error())
}
}

func TestVeterinaryGroupInfo(t *testing.T) {
testCases := []struct {
ResponsibleParty string
PatientName string
}{
{
ResponsibleParty: "Potter",
PatientName: "Hedwig",
},
{
ResponsibleParty: "",
PatientName: "Hedwig",
},
{
ResponsibleParty: "Potter",
PatientName: "",
},
{
ResponsibleParty: "",
PatientName: "",
},
}

for _, tc := range testCases {
name := fmt.Sprintf("%v_%v_new", tc.ResponsibleParty, tc.PatientName)
t.Run(name, func(t *testing.T) {
groupInfo := NewVeterinaryGroupInfo(tc.ResponsibleParty, tc.PatientName)
checkVeterinaryInfo(t, groupInfo, tc.ResponsibleParty, tc.PatientName)
})

name = fmt.Sprintf("%v_%v_set", tc.ResponsibleParty, tc.PatientName)
t.Run(name, func(t *testing.T) {
groupInfo := GroupInfo{}
groupInfo.Veterinary().SetResponsibleParty(tc.ResponsibleParty)
groupInfo.Veterinary().SetPatientName(tc.PatientName)

checkVeterinaryInfo(t, groupInfo, tc.ResponsibleParty, tc.PatientName)
})
}
}

func checkVeterinaryInfo(t *testing.T, groupInfo GroupInfo, expectedParty, expectedPatient string) {
if groupInfo.Veterinary().ResponsibleParty() != expectedParty {
t.Errorf(
"ResponsibleParty() returned %v, expected %v",
groupInfo.Veterinary().ResponsibleParty(),
expectedParty,
)
}

if groupInfo.Veterinary().PatientName() != expectedPatient {
t.Errorf(
"ResponsibleParty() returned %v, expected %v",
groupInfo.Veterinary().PatientName(),
expectedPatient,
)
}

if groupInfo.FamilyName != expectedParty {
t.Errorf(
"groupInfo.FamilyName returned %v, expected %v",
groupInfo.FamilyName,
expectedParty,
)
}

if groupInfo.GivenName != expectedPatient {
t.Errorf(
"groupInfo.GivenName returned %v, expected %v",
groupInfo.GivenName,
expectedPatient,
)
}

if groupInfo.TrailingNullLevel != GroupNullLevelNone {
t.Errorf(
"groupInfo.TrailingNullLevel was %v, expected %v",
groupInfo.TrailingNullLevel,
GroupNullLevelNone,
)
}
}