Commit b7b75f16 authored by Julien Topçu's avatar Julien Topçu
Browse files

Adding controllers

parent a7cbbf9c
......@@ -40,7 +40,7 @@
<plugins>
<plugin>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.0.0-M2</version>
<version>3.0.0-M1</version>
<executions>
<execution>
<id>dependencies-sanitization</id>
......@@ -93,9 +93,6 @@
<args>
<arg>-Xjsr305=strict</arg>
</args>
<compilerPlugins>
<plugin>spring</plugin>
</compilerPlugins>
<jvmTarget>1.8</jvmTarget>
<javaParameters>true</javaParameters>
</configuration>
......
......@@ -39,6 +39,36 @@
</execution>
</executions>
</plugin>
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
<configuration>
<compilerPlugins>
<plugin>all-open</plugin>
</compilerPlugins>
<pluginOptions>
<option>all-open:annotation=org.craftsrecords.hexarch.DomainService</option>
<option>all-open:annotation=org.craftsrecords.hexarch.Stub</option>
</pluginOptions>
</configuration>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-allopen</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
......
package org.craftsrecords.hexarch
import java.lang.annotation.Inherited
@Retention(AnnotationRetention.SOURCE)
@Target(AnnotationTarget.CLASS)
@Inherited
annotation class Aggregate
package org.craftsrecords.hexarch
import java.lang.annotation.Inherited
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.CLASS)
@Inherited
annotation class DomainService
package org.craftsrecords.hexarch
import java.lang.annotation.Inherited
@Retention(AnnotationRetention.SOURCE)
@Target(AnnotationTarget.CLASS)
@Inherited
annotation class Repository
package org.craftsrecords.hexarch
import java.lang.annotation.Inherited
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.CLASS)
@Inherited
annotation class Stub
package org.craftsrecords.talkadvisor.recommendation
import org.craftsrecords.hexarch.Aggregate
import org.craftsrecords.talkadvisor.recommendation.criteria.Criteria
import org.craftsrecords.talkadvisor.recommendation.talk.Talk
import java.util.*
@Aggregate
class Recommendation(val id: UUID = UUID.randomUUID(), talks: Set<Talk>, val criteria: Criteria) {
val talks = talks.toSet()
......
package org.craftsrecords.talkadvisor.recommendation
import org.craftsrecords.hexarch.DomainService
import org.craftsrecords.talkadvisor.recommendation.api.RecommendTalks
import org.craftsrecords.talkadvisor.recommendation.criteria.Criteria
import org.craftsrecords.talkadvisor.recommendation.criteria.GuestCriteria
import org.craftsrecords.talkadvisor.recommendation.profile.ProfileNotFoundException
import org.craftsrecords.talkadvisor.recommendation.spi.Profiles
import org.craftsrecords.talkadvisor.recommendation.spi.Recommendations
import org.craftsrecords.talkadvisor.recommendation.spi.SearchTalks
import org.craftsrecords.talkadvisor.recommendation.talk.Talk
@DomainService
class TalksAdvisor(private val searchTalks: SearchTalks,
private val recommendations: Recommendations,
private val profiles: Profiles) : RecommendTalks {
override fun to(userId: String): Recommendation {
val profile = profiles.fetch(userId)
val profile = profiles.fetch(userId) ?: throw ProfileNotFoundException(userId)
return recommendTalksSatisfying(profile.preferences)
}
......@@ -24,8 +27,7 @@ class TalksAdvisor(private val searchTalks: SearchTalks,
private fun recommendTalksSatisfying(criteria: Criteria): Recommendation {
val talks = retrieveTalksSatisfying(criteria)
val recommendation = Recommendation(criteria = criteria, talks = talks)
recommendations.save(recommendation)
return recommendation
return recommendations.save(recommendation)
}
private fun retrieveTalksSatisfying(criteria: Criteria): Set<Talk> {
......
......@@ -21,6 +21,4 @@ class Profile(id: String, val preferences: Preferences) {
override fun hashCode(): Int {
return id.hashCode()
}
}
\ No newline at end of file
package org.craftsrecords.talkadvisor.recommendation.profile
class ProfileAlreadyExistsException(userId: String) : RuntimeException("A profile already exists for the user $userId")
\ No newline at end of file
package org.craftsrecords.talkadvisor.recommendation.profile
import org.craftsrecords.hexarch.DomainService
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 {
@DomainService
class ProfileCreator(private val profiles: Profiles) : CreateProfile {
override fun forUserWithPreferences(userId: String, preferences: Preferences): Profile {
val profile = Profile(userId, preferences)
profiles.save(profile)
return profile
profiles.fetch(userId)?.let { throw ProfileAlreadyExistsException(userId) }
return profiles.save(profile)
}
}
\ No newline at end of file
package org.craftsrecords.talkadvisor.recommendation.profile
class NoProfileFoundException(val userId: String) : RuntimeException("No profile found to the user $userId")
\ No newline at end of file
class ProfileNotFoundException(val userId: String) : RuntimeException("No profile found for the user $userId")
\ No newline at end of file
package org.craftsrecords.talkadvisor.recommendation.spi
import org.craftsrecords.hexarch.Repository
import org.craftsrecords.talkadvisor.recommendation.profile.Profile
@Repository
interface Profiles {
fun save(profile: Profile)
fun save(profile: Profile): Profile
fun fetch(userId: String): Profile
fun fetch(userId: String): Profile?
}
package org.craftsrecords.talkadvisor.recommendation.spi
import org.craftsrecords.hexarch.Repository
import org.craftsrecords.talkadvisor.recommendation.Recommendation
@Repository
interface Recommendations {
fun save(recommendation: Recommendation)
fun save(recommendation: Recommendation): Recommendation
}
package org.craftsrecords.talkadvisor.recommendation.spi.stubs
import org.craftsrecords.hexarch.Stub
import org.craftsrecords.talkadvisor.recommendation.preferences.Topic
import org.craftsrecords.talkadvisor.recommendation.spi.SearchTalks
import org.craftsrecords.talkadvisor.recommendation.talk.Talk
import java.time.Duration
import kotlin.random.Random
@Stub
class HardCodedTalksSearcher : SearchTalks {
override fun forTopics(topics: Set<Topic>): Set<Talk> {
return createTalks(topics)
......
package org.craftsrecords.talkadvisor.recommendation.spi.stubs
import org.craftsrecords.talkadvisor.recommendation.profile.NoProfileFoundException
import org.craftsrecords.hexarch.Stub
import org.craftsrecords.talkadvisor.recommendation.profile.Profile
import org.craftsrecords.talkadvisor.recommendation.spi.Profiles
@Stub
class InMemoryProfiles(private val profiles: MutableMap<String, Profile> = HashMap()) : Profiles {
override fun fetch(userId: String): Profile {
return profiles[userId] ?: throw NoProfileFoundException(userId)
override fun fetch(userId: String): Profile? {
return profiles[userId]
}
override fun save(profile: Profile) {
override fun save(profile: Profile): Profile {
profiles[profile.id] = profile
return profile
}
}
\ No newline at end of file
package org.craftsrecords.talkadvisor.recommendation.spi.stubs
import org.craftsrecords.hexarch.Stub
import org.craftsrecords.talkadvisor.recommendation.Recommendation
import org.craftsrecords.talkadvisor.recommendation.spi.Recommendations
import java.util.*
@Stub
class InMemoryRecommendations(private val recommendations: MutableMap<UUID, Recommendation> = HashMap()) : Recommendations {
override fun save(recommendation: Recommendation) {
override fun save(recommendation: Recommendation): Recommendation {
recommendations[recommendation.id] = recommendation
return recommendation
}
}
\ No newline at end of file
package org.craftsrecords.talkadvisor
import java.nio.charset.Charset
import kotlin.random.Random
fun Random.nextString() = String(Random.nextBytes(4), Charset.defaultCharset())
\ No newline at end of file
package org.craftsrecords.talkadvisor
package org.craftsrecords.talkadvisor.recommendation
import cucumber.api.CucumberOptions
import cucumber.api.junit.Cucumber
import org.junit.runner.RunWith
@RunWith(Cucumber::class)
@CucumberOptions(strict = true, plugin = ["pretty", "html:target/cucumber"], features = ["classpath:features/"])
class RunCucumberTest
\ No newline at end of file
@CucumberOptions(strict = true, plugin = ["pretty", "html:target/cucumber"], features = ["classpath:features/recommendations.feature"])
class RecommendationFunctionalTests
\ No newline at end of file
package org.craftsrecords.talkadvisor.recommendation
import org.assertj.core.api.Assertions.assertThat
import org.craftsrecords.talkadvisor.recommendation.profile.createCriteria
import org.craftsrecords.talkadvisor.recommendation.criteria.createCriteria
import org.craftsrecords.talkadvisor.recommendation.talk.createTalk
import org.craftsrecords.talkadvisor.recommendation.talk.createTalks
import org.junit.jupiter.api.Test
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment