Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
What's new
4
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Switch to GitLab Next
Sign in / Register
Toggle navigation
Menu
Open sidebar
CraftsRecords
TalkAdvisor
TalkAdvisor BackEnd
Commits
4ed495dc
Commit
4ed495dc
authored
Feb 20, 2019
by
Julien Topçu
Browse files
Create Profile Feature
parent
03bda253
Changes
23
Hide whitespace changes
Inline
Side-by-side
talkadvisor-domain/src/main/java/org/craftsrecords/talkadvisor/recommendation/api/CreateProfile.java
0 → 100644
View file @
4ed495dc
package
org.craftsrecords.talkadvisor.recommendation.api
;
import
org.craftsrecords.talkadvisor.recommendation.preferences.Preferences
;
import
org.craftsrecords.talkadvisor.recommendation.profile.Profile
;
import
javax.annotation.Nonnull
;
@FunctionalInterface
public
interface
CreateProfile
{
@Nonnull
Profile
forUserWithPreferences
(
@Nonnull
String
userId
,
@Nonnull
Preferences
preferences
);
}
talkadvisor-domain/src/main/java/org/craftsrecords/talkadvisor/recommendation/spi/Profiles.java
0 → 100644
View file @
4ed495dc
package
org.craftsrecords.talkadvisor.recommendation.spi
;
import
org.craftsrecords.talkadvisor.recommendation.profile.Profile
;
public
interface
Profiles
{
void
save
(
Profile
profile
);
}
talkadvisor-domain/src/main/java/org/craftsrecords/talkadvisor/recommendation/spi/SearchTalks.java
View file @
4ed495dc
...
...
@@ -9,5 +9,5 @@ import java.util.Set;
@FunctionalInterface
public
interface
SearchTalks
{
@Nonnull
Set
<
Talk
>
forTopic
(
@Nonnull
Topic
topic
);
Set
<
Talk
>
forTopic
s
(
@Nonnull
Set
<
Topic
>
topic
s
);
}
talkadvisor-domain/src/main/kotlin/org/craftsrecords/talkadvisor/recommendation/TalksAdvisor.kt
View file @
4ed495dc
...
...
@@ -16,7 +16,7 @@ class TalksAdvisor(private val searchTalks: SearchTalks, private val recommendat
}
private
fun
getTalksSatisfying
(
preferences
:
Preferences
):
Set
<
Talk
>
{
return
searchTalks
.
forTopic
(
preferences
.
topic
)
return
searchTalks
.
forTopic
s
(
preferences
.
topic
s
)
.
filter
{
preferences
.
talksFormats
.
contains
(
it
.
format
)
}
.
toSet
()
}
...
...
talkadvisor-domain/src/main/kotlin/org/craftsrecords/talkadvisor/recommendation/preferences/Preferences.kt
View file @
4ed495dc
...
...
@@ -2,6 +2,27 @@ package org.craftsrecords.talkadvisor.recommendation.preferences
import
org.craftsrecords.talkadvisor.recommendation.talk.TalkFormat
class
Preferences
(
val
topic
:
Topic
,
talksFormats
:
Set
<
TalkFormat
>)
{
class
Preferences
(
topic
s
:
Set
<
Topic
>
,
talksFormats
:
Set
<
TalkFormat
>)
{
val
talksFormats
:
Set
<
TalkFormat
>
=
talksFormats
.
toSet
()
val
topics
:
Set
<
Topic
>
=
topics
.
toSet
()
override
fun
equals
(
other
:
Any
?):
Boolean
{
if
(
this
===
other
)
return
true
if
(
javaClass
!=
other
?.
javaClass
)
return
false
other
as
Preferences
if
(
talksFormats
!=
other
.
talksFormats
)
return
false
if
(
topics
!=
other
.
topics
)
return
false
return
true
}
override
fun
hashCode
():
Int
{
var
result
=
talksFormats
.
hashCode
()
result
=
31
*
result
+
topics
.
hashCode
()
return
result
}
}
\ No newline at end of file
talkadvisor-domain/src/main/kotlin/org/craftsrecords/talkadvisor/recommendation/preferences/Topic.kt
View file @
4ed495dc
...
...
@@ -4,4 +4,19 @@ import org.apache.commons.lang3.Validate.notBlank
class
Topic
(
name
:
String
)
{
val
name
:
String
=
notBlank
(
name
,
"Cannot create a topic with a blank name"
)
override
fun
equals
(
other
:
Any
?):
Boolean
{
if
(
this
===
other
)
return
true
if
(
javaClass
!=
other
?.
javaClass
)
return
false
other
as
Topic
if
(
name
!=
other
.
name
)
return
false
return
true
}
override
fun
hashCode
():
Int
{
return
name
.
hashCode
()
}
}
talkadvisor-domain/src/main/kotlin/org/craftsrecords/talkadvisor/recommendation/profile/Profile.kt
0 → 100644
View file @
4ed495dc
package
org.craftsrecords.talkadvisor.recommendation.profile
import
org.apache.commons.lang3.Validate.notBlank
import
org.craftsrecords.talkadvisor.recommendation.preferences.Preferences
class
Profile
(
id
:
String
,
val
preferences
:
Preferences
)
{
val
id
=
notBlank
(
id
,
"Cannot create a Profile is a blank id"
)
override
fun
equals
(
other
:
Any
?):
Boolean
{
if
(
this
===
other
)
return
true
if
(
javaClass
!=
other
?.
javaClass
)
return
false
other
as
Profile
if
(
id
!=
other
.
id
)
return
false
return
true
}
override
fun
hashCode
():
Int
{
return
id
.
hashCode
()
}
}
\ No newline at end of file
talkadvisor-domain/src/main/kotlin/org/craftsrecords/talkadvisor/recommendation/profile/ProfileCreator.kt
0 → 100644
View file @
4ed495dc
package
org.craftsrecords.talkadvisor.recommendation.profile
import
org.craftsrecords.talkadvisor.recommendation.api.CreateProfile
import
org.craftsrecords.talkadvisor.recommendation.preferences.Preferences
import
org.craftsrecords.talkadvisor.recommendation.spi.Profiles
class
ProfileCreator
(
val
profiles
:
Profiles
)
:
CreateProfile
{
override
fun
forUserWithPreferences
(
userId
:
String
,
preferences
:
Preferences
):
Profile
{
val
profile
=
Profile
(
userId
,
preferences
)
profiles
.
save
(
profile
)
return
profile
}
}
\ No newline at end of file
talkadvisor-domain/src/main/kotlin/org/craftsrecords/talkadvisor/recommendation/spi/stubs/HardCodedTalksSearcher.kt
View file @
4ed495dc
...
...
@@ -7,16 +7,20 @@ import java.time.Duration
import
kotlin.random.Random
class
HardCodedTalksSearcher
:
SearchTalks
{
override
fun
forTopic
(
topic
:
Topic
):
Set
<
Talk
>
{
return
createTalks
(
topic
)
override
fun
forTopic
s
(
topic
s
:
Set
<
Topic
>
):
Set
<
Talk
>
{
return
createTalks
(
topic
s
)
}
private
fun
createTalks
(
topic
:
Topic
):
Set
<
Talk
>
{
return
(
1
..
20
)
private
fun
createTalks
(
topics
:
Set
<
Topic
>):
Set
<
Talk
>
{
return
topics
.
flatMap
{
createTalksForTopic
(
it
.
name
)
}.
shuffled
().
toSet
()
}
private
fun
createTalksForTopic
(
topicName
:
String
):
Set
<
Talk
>
{
return
(
1
..
30
)
.
map
{
Talk
.
with
{
id
=
it
.
toString
()
title
=
"${randomText()} $
{
topic
.n
ame
}
${randomText()}"
title
=
"${randomText()} $topic
N
ame ${randomText()}"
duration
=
Duration
.
ofMinutes
(
Random
.
nextLong
(
2
,
100
))
}.
build
()
}.
toSet
()
...
...
talkadvisor-domain/src/main/kotlin/org/craftsrecords/talkadvisor/recommendation/spi/stubs/InMemoryProfiles.kt
0 → 100644
View file @
4ed495dc
package
org.craftsrecords.talkadvisor.recommendation.spi.stubs
import
org.craftsrecords.talkadvisor.recommendation.profile.Profile
import
org.craftsrecords.talkadvisor.recommendation.spi.Profiles
class
InMemoryProfiles
(
private
val
profiles
:
MutableMap
<
String
,
Profile
>
=
HashMap
())
:
Profiles
{
override
fun
save
(
profile
:
Profile
)
{
profiles
[
profile
.
id
]
=
profile
}
}
\ No newline at end of file
talkadvisor-domain/src/main/kotlin/org/craftsrecords/talkadvisor/recommendation/talk/Talk.kt
View file @
4ed495dc
...
...
@@ -9,8 +9,8 @@ class Talk private constructor(id: String,
title
:
String
,
duration
:
Duration
)
{
val
id
=
notBlank
(
id
,
"Cannot create a Talk is a blank id"
)
val
title
=
notBlank
(
title
,
"Cannot create a Talk is a blank title"
)
val
id
=
notBlank
(
id
,
"Cannot create a Talk is a blank id"
)
!!
val
title
=
notBlank
(
title
,
"Cannot create a Talk is a blank title"
)
!!
val
duration
=
notNegative
(
duration
)
val
format
=
TalkFormat
.
ofDuration
(
duration
)
...
...
talkadvisor-domain/src/test/java/org/craftsrecords/talkadvisor/recommendation/stepdefs/PreferencesStepdefs.java
View file @
4ed495dc
package
org.craftsrecords.talkadvisor.recommendation.stepdefs
;
import
cucumber.api.java8.En
;
import
io.cucumber.datatable.DataTable
;
import
org.craftsrecords.talkadvisor.recommendation.preferences.Topic
;
import
org.craftsrecords.talkadvisor.recommendation.talk.TalkFormat
;
import
java.util.Set
;
import
static
java
.
util
.
Collections
.
singleton
;
import
static
java
.
util
.
stream
.
Collectors
.
toSet
;
public
class
PreferencesStepdefs
implements
En
{
public
PreferencesStepdefs
(
TestContext
testContext
)
{
Given
(
"^a guest user who wants to learn (.+)"
,
(
String
topicName
)
->
testContext
.
setRequestedTopic
(
new
Topic
(
topicName
)));
(
String
topicName
)
->
testContext
.
setRequestedTopics
(
singleton
(
new
Topic
(
topicName
))));
Given
(
"^he has only time to watch (.+) talks$"
,
(
String
format
)
->
{
Set
<
TalkFormat
>
talkFormats
=
singleton
(
TalkFormat
.
valueOf
(
format
));
testContext
.
setRequestedTalksFormats
(
talkFormats
);
});
Given
(
"^a user$"
,
()
->
{
testContext
.
setUserId
(
"frequentUser"
);
});
Given
(
"^he wants to learn$"
,
(
DataTable
topicNames
)
->
{
Set
<
Topic
>
topics
=
topicNames
.
asList
()
.
stream
()
.
map
(
Topic:
:
new
)
.
collect
(
toSet
());
testContext
.
setRequestedTopics
(
topics
);
});
Given
(
"^he only wants to see$"
,
(
DataTable
formats
)
->
{
Set
<
TalkFormat
>
talkFormats
=
formats
.
asList
().
stream
().
map
(
TalkFormat:
:
valueOf
).
collect
(
toSet
());
testContext
.
setRequestedTalksFormats
(
talkFormats
);
});
}
}
talkadvisor-domain/src/test/java/org/craftsrecords/talkadvisor/recommendation/stepdefs/ProfileStepdefs.java
0 → 100644
View file @
4ed495dc
package
org.craftsrecords.talkadvisor.recommendation.stepdefs
;
import
cucumber.api.java8.En
;
import
org.craftsrecords.talkadvisor.recommendation.api.CreateProfile
;
import
org.craftsrecords.talkadvisor.recommendation.preferences.Preferences
;
import
org.craftsrecords.talkadvisor.recommendation.profile.Profile
;
import
static
org
.
craftsrecords
.
talkadvisor
.
recommendation
.
assertions
.
TalkAdvisorAssertions
.
assertThat
;
public
class
ProfileStepdefs
implements
En
{
public
ProfileStepdefs
(
TestContext
testContext
,
CreateProfile
createProfile
)
{
When
(
"^he creates his profile$"
,
()
->
{
Preferences
preferences
=
new
Preferences
(
testContext
.
getRequestedTopics
(),
testContext
.
getRequestedTalksFormats
());
Profile
profile
=
createProfile
.
forUserWithPreferences
(
testContext
.
getUserId
(),
preferences
);
testContext
.
setRequestedPreferences
(
preferences
);
testContext
.
setCreatedProfile
(
profile
);
});
Then
(
"^his preferences are stored within$"
,
()
->
{
Profile
profile
=
testContext
.
getCreatedProfile
();
assertThat
(
profile
).
correspondToUser
(
testContext
.
getUserId
());
assertThat
(
profile
).
hasPreferences
(
testContext
.
getRequestedPreferences
());
});
}
}
talkadvisor-domain/src/test/java/org/craftsrecords/talkadvisor/recommendation/stepdefs/RecommendationStepdefs.java
View file @
4ed495dc
...
...
@@ -42,6 +42,6 @@ public class RecommendationStepdefs implements En {
}
private
Preferences
createCriteriaFrom
(
TestContext
testContext
)
{
return
new
Preferences
(
testContext
.
getRequestedTopic
(),
testContext
.
getRequestedTalksFormats
());
return
new
Preferences
(
testContext
.
getRequestedTopic
s
(),
testContext
.
getRequestedTalksFormats
());
}
}
talkadvisor-domain/src/test/kotlin/org/craftsrecords/talkadvisor/CustomPicoFactory.kt
View file @
4ed495dc
...
...
@@ -2,7 +2,9 @@ package org.craftsrecords.talkadvisor
import
cucumber.runtime.java.picocontainer.PicoFactory
import
org.craftsrecords.talkadvisor.recommendation.TalksAdvisor
import
org.craftsrecords.talkadvisor.recommendation.profile.ProfileCreator
import
org.craftsrecords.talkadvisor.recommendation.spi.stubs.HardCodedTalksSearcher
import
org.craftsrecords.talkadvisor.recommendation.spi.stubs.InMemoryProfiles
import
org.craftsrecords.talkadvisor.recommendation.spi.stubs.InMemoryRecommendations
import
org.craftsrecords.talkadvisor.recommendation.stepdefs.TestContext
...
...
@@ -12,5 +14,7 @@ class CustomPicoFactory : PicoFactory() {
addClass
(
TalksAdvisor
::
class
.
java
)
addClass
(
HardCodedTalksSearcher
::
class
.
java
)
addClass
(
InMemoryRecommendations
::
class
.
java
)
addClass
(
ProfileCreator
::
class
.
java
)
addClass
(
InMemoryProfiles
::
class
.
java
)
}
}
\ No newline at end of file
talkadvisor-domain/src/test/kotlin/org/craftsrecords/talkadvisor/recommendation/assertions/ProfileAssert.kt
0 → 100644
View file @
4ed495dc
package
org.craftsrecords.talkadvisor.recommendation.assertions
import
org.assertj.core.api.AbstractAssert
import
org.craftsrecords.talkadvisor.recommendation.preferences.Preferences
import
org.craftsrecords.talkadvisor.recommendation.profile.Profile
class
ProfileAssert
(
actual
:
Profile
)
:
AbstractAssert
<
ProfileAssert
,
Profile
>(
actual
,
ProfileAssert
::
class
.
java
)
{
@JvmName
(
"correspondToUser"
)
fun
`correspond
to
user`
(
userId
:
String
)
{
matches
({
actual
.
id
==
userId
},
"profile id corresponds to userId"
)
}
@JvmName
(
"hasPreferences"
)
fun
`has
preferences`
(
preferences
:
Preferences
)
{
matches
({
actual
.
preferences
==
preferences
},
"matching expected preferences"
)
}
}
talkadvisor-domain/src/test/kotlin/org/craftsrecords/talkadvisor/recommendation/assertions/TalkAdvisorAssertions.kt
View file @
4ed495dc
...
...
@@ -2,6 +2,7 @@ package org.craftsrecords.talkadvisor.recommendation.assertions
import
org.assertj.core.api.Assertions
import
org.craftsrecords.talkadvisor.recommendation.Recommendation
import
org.craftsrecords.talkadvisor.recommendation.profile.Profile
import
org.craftsrecords.talkadvisor.recommendation.talk.Talk
class
TalkAdvisorAssertions
:
Assertions
()
{
...
...
@@ -14,5 +15,8 @@ class TalkAdvisorAssertions : Assertions() {
@JvmStatic
fun
assertThat
(
actual
:
Iterable
<
Talk
>)
=
TalksAssert
(
actual
)
@JvmStatic
fun
assertThat
(
actual
:
Profile
)
=
ProfileAssert
(
actual
)
}
}
\ No newline at end of file
talkadvisor-domain/src/test/kotlin/org/craftsrecords/talkadvisor/recommendation/preferences/PreferencesTest.kt
View file @
4ed495dc
...
...
@@ -11,11 +11,40 @@ internal class PreferencesTest {
fun
`should
store
a
copy
of
the
talks
formats`
()
{
val
talksFormats
=
mutableSetOf
(
CONFERENCE
)
val
criteria
=
Preferences
(
Topic
(
"ddd"
),
talksFormats
)
val
preferences
=
Preferences
(
setOf
(
Topic
(
"ddd"
)
)
,
talksFormats
)
talksFormats
.
add
(
QUICKIE
)
assertThat
(
criteria
.
talksFormats
).
containsOnly
(
CONFERENCE
)
assertThat
(
preferences
.
talksFormats
).
containsOnly
(
CONFERENCE
)
}
@Test
fun
`should
store
a
copy
of
the
topics`
()
{
val
topics
=
mutableSetOf
(
Topic
(
"ddd"
))
val
preferences
=
Preferences
(
topics
,
setOf
(
CONFERENCE
))
val
newTopic
=
Topic
(
"new"
)
topics
.
add
(
newTopic
)
assertThat
(
preferences
.
topics
).
doesNotContain
(
newTopic
)
}
@Test
fun
`should
satisfy
value
object
equality`() {
val preferences =
Preferences
(
setOf
(
Topic
(
"ddd"
)),
setOf
(
CONFERENCE
))
val
preferences2
=
Preferences
(
setOf
(
Topic
(
"ddd"
)),
setOf
(
CONFERENCE
))
assertThat
(
preferences
).
isEqualTo
(
preferences2
)
assertThat
(
preferences
.
hashCode
()).
isEqualTo
(
preferences2
.
hashCode
())
}
@Test
fun
`should
satisfy
value
object
inequality`() {
val preferences =
Preferences
(
setOf
(
Topic
(
"ddd"
)),
setOf
(
CONFERENCE
))
val
preferences2
=
Preferences
(
setOf
(
Topic
(
"ddd"
)),
setOf
(
QUICKIE
))
assertThat
(
preferences
).
isNotEqualTo
(
preferences2
)
assertThat
(
preferences
.
hashCode
()).
isNotEqualTo
(
preferences2
.
hashCode
())
}
}
talkadvisor-domain/src/test/kotlin/org/craftsrecords/talkadvisor/recommendation/preferences/TopicTest.kt
View file @
4ed495dc
package
org.craftsrecords.talkadvisor.recommendation.preferences
import
org.assertj.core.api.Assertions.assertThat
import
org.assertj.core.api.Assertions.assertThatThrownBy
import
org.junit.jupiter.api.Test
...
...
@@ -11,4 +12,22 @@ internal class TopicTest {
.
isInstanceOf
(
IllegalArgumentException
::
class
.
java
)
.
hasMessage
(
"Cannot create a topic with a blank name"
)
}
@Test
fun
`should
satisfy
value
object
equality`() {
val topic =
Topic
(
"topic"
)
val
topic2
=
Topic
(
"topic"
)
assertThat
(
topic
).
isEqualTo
(
topic2
)
assertThat
(
topic
.
hashCode
()).
isEqualTo
(
topic2
.
hashCode
())
}
@Test
fun
`should
satisfy
value
object
inequality`() {
val topic =
Topic
(
"topic"
)
val
topic2
=
Topic
(
"topic2"
)
assertThat
(
topic
).
isNotEqualTo
(
topic2
)
assertThat
(
topic
.
hashCode
()).
isNotEqualTo
(
topic2
.
hashCode
())
}
}
\ No newline at end of file
talkadvisor-domain/src/test/kotlin/org/craftsrecords/talkadvisor/recommendation/profile/PreferencesFactory.kt
0 → 100644
View file @
4ed495dc
package
org.craftsrecords.talkadvisor.recommendation.profile
import
org.craftsrecords.talkadvisor.recommendation.preferences.Preferences
import
org.craftsrecords.talkadvisor.recommendation.preferences.Topic
import
org.craftsrecords.talkadvisor.recommendation.talk.TalkFormat
import
kotlin.random.Random
fun
createPreferences
()
=
Preferences
(
setOf
(
Topic
(
Random
.
nextInt
().
toString
()),
Topic
(
Random
.
nextInt
().
toString
())),
setOf
(
TalkFormat
.
CONFERENCE
,
TalkFormat
.
QUICKIE
))
Prev
1
2
Next
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment