Skip to content

Commit 089337d

Browse files
authored
Merge pull request #78 from RADAR-base/release-1.0.6
Release 1.0.6
2 parents ed70d2e + 26400e4 commit 089337d

File tree

9 files changed

+91
-39
lines changed

9 files changed

+91
-39
lines changed

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ plugins {
99
}
1010

1111
group = 'org.radarbase'
12-
version = '1.0.5'
12+
version = '1.0.6'
1313

1414
application {
1515
mainClass = 'org.radarbase.redcap.webapp.GrizzlyServer'

src/integration-test/kotlin/org/radarbase/redcap/EntryPointTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ class EntryPointTest {
3434
val subject: Subject? =
3535
mpClient.getSubject(URL(REDCAP_URL), REDCAP_PROJECT_ID, REDCAP_RECORD_ID_2)
3636
Assert.assertNotNull(subject)
37-
Assert.assertEquals(Integer.valueOf(REDCAP_RECORD_ID_2), subject?.externalId)
37+
Assert.assertEquals(REDCAP_RECORD_ID_2.toString(), subject?.externalId)
3838
Assert.assertEquals(
3939
"$WORK_PACKAGE-$MP_PROJECT_ID-$MP_PROJECT_LOCATION-$REDCAP_RECORD_ID_2",
4040
subject?.humanReadableIdentifier

src/integration-test/kotlin/org/radarbase/redcap/integration/IntegratorTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ class IntegratorTest {
105105

106106
assertNotNull(subject)
107107
assertEquals(
108-
Integer.valueOf(REDCAP_RECORD_ID_2),
108+
REDCAP_RECORD_ID_2.toString(),
109109
subject?.externalId
110110
)
111111
assertEquals(

src/integration-test/kotlin/org/radarbase/redcap/managementportal/MpClientTest.kt

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ import java.net.URL
1515
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
1616
class MpClientTest {
1717
private var project: Project? = null
18-
private val testAttributes: Map<String, String> =
19-
HashMap()
18+
private val emptyAttributes: Map<String, String> = HashMap()
19+
private val attributes: Map<String, String> = mapOf("group" to "test")
2020

2121
@Before
2222
@Throws(IOException::class, TokenException::class)
@@ -42,7 +42,7 @@ class MpClientTest {
4242
}
4343
mpClient.createSubject(
4444
URL(IntegrationUtils.REDCAP_URL), project!!, IntegrationUtils.REDCAP_RECORD_ID_1,
45-
IntegrationUtils.WORK_PACKAGE + IntegrationUtils.REDCAP_RECORD_ID_1, testAttributes
45+
IntegrationUtils.WORK_PACKAGE + IntegrationUtils.REDCAP_RECORD_ID_1, emptyAttributes
4646
)
4747
val subject =
4848
mpClient.getSubject(
@@ -51,7 +51,7 @@ class MpClientTest {
5151
)
5252
Assert.assertNotNull(subject)
5353
Assert.assertEquals(
54-
Integer.valueOf(IntegrationUtils.REDCAP_RECORD_ID_1),
54+
IntegrationUtils.REDCAP_RECORD_ID_1.toString(),
5555
subject!!.externalId
5656
)
5757
Assert.assertEquals(
@@ -69,7 +69,27 @@ class MpClientTest {
6969
// This should throw exception since subject already exists
7070
mpClient.createSubject(
7171
URL(IntegrationUtils.REDCAP_URL), project!!, IntegrationUtils.REDCAP_RECORD_ID_1,
72-
IntegrationUtils.WORK_PACKAGE + IntegrationUtils.REDCAP_RECORD_ID_1, testAttributes
72+
IntegrationUtils.WORK_PACKAGE + IntegrationUtils.REDCAP_RECORD_ID_1, emptyAttributes
7373
)
7474
}
75+
76+
@Test
77+
@Throws(IOException::class, URISyntaxException::class)
78+
fun updateSubjectTest() {
79+
if (project == null) {
80+
projectTest()
81+
}
82+
val subject =
83+
mpClient.getSubject(
84+
URL(IntegrationUtils.REDCAP_URL), IntegrationUtils.REDCAP_PROJECT_ID,
85+
IntegrationUtils.REDCAP_RECORD_ID_1
86+
)
87+
subject?.addAttributes(attributes)
88+
val newSubject = mpClient.updateSubject(subject!!)
89+
90+
Assert.assertNotNull(newSubject)
91+
Assert.assertEquals(subject, newSubject)
92+
Assert.assertEquals(subject.attributes, newSubject.attributes)
93+
Assert.assertEquals(subject.sources, newSubject.sources)
94+
}
7595
}

src/main/kotlin/org/radarbase/redcap/config/RedCapManager.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ object RedCapManager {
9797
* @throws NoSuchElementException In case the [URL] does not contain any characters
9898
*/
9999
@Throws(MalformedURLException::class, NoSuchElementException::class)
100-
fun getRecordUrl(redCapUrl: URL, projectId: Int, recordId: Int): URL {
100+
fun getRecordUrl(redCapUrl: URL, projectId: Int, recordId: Int): String {
101101
val redCapInfo = getRedCapInfo(redCapUrl, projectId)
102102
var redCap = redCapInfo.url.toString()
103103

@@ -107,6 +107,6 @@ object RedCapManager {
107107

108108
redCap = "$redCap$PROJECT_ID$projectId$RECORD_ID$recordId" +
109109
"$EVENT_ID${redCapInfo.enrolmentEvent}$PAGE_NAME${redCapInfo.integrationForm}"
110-
return URL(redCap)
110+
return URL(redCap).toString()
111111
}
112112
}

src/main/kotlin/org/radarbase/redcap/managementportal/MpClient.kt

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -129,15 +129,16 @@ open class MpClient @Inject constructor(private val httpClient: OkHttpClient) {
129129
val radarSubjectId = UUID.randomUUID().toString()
130130
val subject = Subject(
131131
subjectId = radarSubjectId,
132-
externalId = recordId,
132+
externalId = recordId.toString(),
133133
externalLink = RedCapManager.getRecordUrl(
134134
redcapUrl,
135135
project.redCapId!!,
136136
recordId
137137
),
138138
project = project,
139139
humanReadableId = humanReadableId,
140-
attributes = attributes
140+
attributes = attributes,
141+
sources = listOf()
141142
)
142143
val request =
143144
getBuilder(Properties.subjectEndPoint).post(
@@ -182,26 +183,23 @@ open class MpClient @Inject constructor(private val httpClient: OkHttpClient) {
182183
recordId
183184
)
184185
).get().build()
185-
186186
return performRequest(
187187
request = request,
188188
onSuccess = { response ->
189-
val subjects =
190-
Subject.subjects(
191-
response
192-
)
193-
if (subjects.size == 0) {
194-
LOGGER.info("Subject is not present")
189+
val subjects = Subject.subjects(response)
190+
.filter { it.externalId.toString() == recordId.toString() }
191+
if (subjects.isEmpty()) {
192+
LOGGER.info("Subject with externalId $recordId is not present")
195193
return@performRequest null
196194
}
195+
197196
check(subjects.size <= 1) {
198-
("More than 1 subjects exist with same "
199-
+ "externalId in the same Project")
197+
"More than one subject exists with the same externalId ($recordId) in the same project"
200198
}
201-
subjects[0]
199+
subjects.first()
202200
},
203201
onError = {
204-
LOGGER.info("Subject is not present")
202+
LOGGER.info("Failed to retrieve subject with externalId $recordId")
205203
null
206204
},
207205
errorMessage = "Subject could not be retrieved"
@@ -264,6 +262,7 @@ open class MpClient @Inject constructor(private val httpClient: OkHttpClient) {
264262
.addPathSegment(projectName)
265263
.addPathSegment("subjects")
266264
.addQueryParameter("externalId", recordId.toString())
265+
.addQueryParameter("size", Int.MAX_VALUE.toString())
267266
.build()
268267
return subjectUrl.toUrl()
269268
}

src/main/kotlin/org/radarbase/redcap/managementportal/Organization.kt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ package org.radarbase.redcap.managementportal
33
import com.fasterxml.jackson.core.JsonParser
44
import com.fasterxml.jackson.databind.DeserializationContext
55
import com.fasterxml.jackson.databind.JsonDeserializer
6+
import com.fasterxml.jackson.core.JsonGenerator
7+
import com.fasterxml.jackson.databind.JsonSerializer
8+
import com.fasterxml.jackson.databind.SerializerProvider
69
import com.fasterxml.jackson.databind.ObjectMapper
710
import com.fasterxml.jackson.databind.JsonNode
811
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
@@ -33,4 +36,17 @@ class OrganizationDeserializer : JsonDeserializer<Organization>() {
3336
}
3437
}
3538
}
39+
}
40+
41+
class OrganizationSerializer : JsonSerializer<Organization>() {
42+
override fun serialize(value: Organization, gen: JsonGenerator, serializers: SerializerProvider) {
43+
when (value) {
44+
is Organization.StringOrganization -> {
45+
gen.writeString(value.value)
46+
}
47+
is Organization.ObjectOrganization -> {
48+
gen.writeObject(value.value)
49+
}
50+
}
51+
}
3652
}

src/main/kotlin/org/radarbase/redcap/managementportal/Project.kt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package org.radarbase.redcap.managementportal
33
import com.fasterxml.jackson.annotation.JsonIgnore
44
import com.fasterxml.jackson.annotation.JsonProperty
55
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
6+
import com.fasterxml.jackson.databind.annotation.JsonSerialize
67
import com.fasterxml.jackson.databind.DeserializationFeature
78
import com.fasterxml.jackson.databind.ObjectMapper
89
import com.fasterxml.jackson.module.kotlin.KotlinModule
@@ -32,7 +33,12 @@ import org.radarbase.redcap.managementportal.Organization
3233
data class Project(
3334
@JsonProperty("id") val id: Int,
3435
@JsonProperty("projectName") val projectName: String,
35-
@JsonProperty("organization") @JsonDeserialize(using = OrganizationDeserializer::class) val organization: Organization,
36+
37+
@JsonProperty("organization")
38+
@JsonDeserialize(using = OrganizationDeserializer::class)
39+
@JsonSerialize(using = OrganizationSerializer::class)
40+
val organization: Organization,
41+
3642
@JsonProperty("location") val location: String = "",
3743
@JsonProperty("attributes") val attributes: Map<String, String> = emptyMap()
3844
) {

src/main/kotlin/org/radarbase/redcap/managementportal/Subject.kt

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -31,19 +31,20 @@ import java.net.URL
3131
/**
3232
* Constructor.
3333
* @param subjectId [String] representing Management Portal Subject identifier
34-
* @param externalId [Integer] representing the REDCap Record identifier
35-
* @param externalLink [URL] pointing the REDCap integration form / instrument
34+
* @param externalId [String] representing the REDCap Record identifier
35+
* @param externalLink [String] pointing the REDCap integration form / instrument
3636
* @param project [Project] associated with the subject
3737
* @param attributes [Map] of key,value pairs
3838
*/
3939
data class Subject(
4040
@JsonProperty("id") val mpId: Long?,
4141
@JsonProperty("login") val subjectId: String,
42-
@JsonProperty("externalId") val externalId: Int? = null,
43-
@JsonProperty("externalLink") val externalLink: URL? = null,
42+
@JsonProperty("externalId") val externalId: String? = null,
43+
@JsonProperty("externalLink") val externalLink: String? = null,
4444
@JsonProperty("project") var project: Project? = null,
4545
@JsonProperty("attributes") val attributes: MutableMap<String, String> = mutableMapOf(),
46-
@JsonProperty("status") val status: String = SubjectStatus.ACTIVATED.toString()
46+
@JsonProperty("status") val status: String = SubjectStatus.ACTIVATED.toString(),
47+
@JsonProperty("sources") val sources: List<JsonNode>
4748
) {
4849
enum class SubjectStatus {
4950
DEACTIVATED, ACTIVATED, DISCONTINUED, INVALID
@@ -57,32 +58,42 @@ data class Subject(
5758
var operationStatus: SubjectOperationStatus =
5859
SubjectOperationStatus.NOOP
5960

60-
6161
/**
6262
* Constructor.
6363
* @param subjectId [String] representing Management Portal Subject identifier
6464
* @param externalId [Integer] representing the REDCap Record identifier
65-
* @param externalLink [URL] pointing the REDCap integration form / instrument
65+
* @param [URL] pointing the REDCap integration form / instrument
6666
* @param project [Project] associated with the subject
6767
* @param humanReadableId [String] representing the value associated with
6868
* [.HUMAN_READABLE_IDENTIFIER_KEY]
6969
*/
7070
constructor(
71-
subjectId: String, externalId: Int, externalLink: URL, project: Project,
72-
humanReadableId: String
71+
subjectId: String,
72+
externalId: String,
73+
externalLink: String,
74+
project: Project,
75+
humanReadableId: String,
76+
sources: List<JsonNode>
7377
) : this(
74-
null, subjectId, externalId, externalLink, project,
75-
mutableMapOf<String, String>(Pair(HUMAN_READABLE_IDENTIFIER_KEY, humanReadableId))
78+
null,
79+
subjectId,
80+
externalId,
81+
externalLink,
82+
project,
83+
mutableMapOf(Pair(HUMAN_READABLE_IDENTIFIER_KEY, humanReadableId)),
84+
SubjectStatus.ACTIVATED.toString(),
85+
sources
7686
)
7787

7888
constructor(
7989
subjectId: String,
80-
externalId: Int,
81-
externalLink: URL,
90+
externalId: String,
91+
externalLink: String,
8292
project: Project,
8393
humanReadableId: String,
84-
attributes: Map<String, String>
85-
) : this(subjectId, externalId, externalLink, project, humanReadableId) {
94+
attributes: Map<String, String>,
95+
sources: List<JsonNode>
96+
) : this(subjectId, externalId, externalLink, project, humanReadableId, sources) {
8697
addAttributes(attributes)
8798
}
8899

0 commit comments

Comments
 (0)