From 23280afc3c3be047e4fd9421aa42153ad8f168e2 Mon Sep 17 00:00:00 2001
From: stonedmoose <jlhermite@ippon.fr>
Date: Mon, 19 Oct 2020 09:51:25 +0200
Subject: [PATCH] Java Trip service kata

---
 .gitlab-ci.yml                                |   1 +
 README.md                                     |   1 +
 package-lock.json                             | 201 ++++++++++++++++++
 package.json                                  |   1 +
 trip-service-kata/.gitlab-ci.yml              |  11 +
 trip-service-kata/pom.xml                     |  36 ++++
 trip-service-kata/readme.md                   |  32 +++
 .../tripservicekata/TripService_Original.java |  34 +++
 .../exception/CollaboratorCallException.java  |  25 +++
 .../exception/UserNotLoggedInException.java   |   7 +
 .../craftedsw/tripservicekata/trip/Trip.java  |   5 +
 .../tripservicekata/trip/TripDAO.java         |  17 ++
 .../tripservicekata/trip/TripService.java     |  39 ++++
 .../craftedsw/tripservicekata/trip/Trips.java |   8 +
 .../craftedsw/tripservicekata/user/User.java  |  29 +++
 .../tripservicekata/user/UserSession.java     |  21 ++
 .../tripservicekata/trip/TripDAOTest.java     |   3 +
 .../tripservicekata/trip/TripServiceTest.java |  61 ++++++
 18 files changed, 532 insertions(+)
 create mode 100644 trip-service-kata/.gitlab-ci.yml
 create mode 100644 trip-service-kata/pom.xml
 create mode 100644 trip-service-kata/readme.md
 create mode 100644 trip-service-kata/src/main/java/org/craftedsw/tripservicekata/TripService_Original.java
 create mode 100644 trip-service-kata/src/main/java/org/craftedsw/tripservicekata/exception/CollaboratorCallException.java
 create mode 100644 trip-service-kata/src/main/java/org/craftedsw/tripservicekata/exception/UserNotLoggedInException.java
 create mode 100644 trip-service-kata/src/main/java/org/craftedsw/tripservicekata/trip/Trip.java
 create mode 100644 trip-service-kata/src/main/java/org/craftedsw/tripservicekata/trip/TripDAO.java
 create mode 100644 trip-service-kata/src/main/java/org/craftedsw/tripservicekata/trip/TripService.java
 create mode 100644 trip-service-kata/src/main/java/org/craftedsw/tripservicekata/trip/Trips.java
 create mode 100644 trip-service-kata/src/main/java/org/craftedsw/tripservicekata/user/User.java
 create mode 100644 trip-service-kata/src/main/java/org/craftedsw/tripservicekata/user/UserSession.java
 create mode 100644 trip-service-kata/src/test/java/org/craftedsw/tripservicekata/trip/TripDAOTest.java
 create mode 100644 trip-service-kata/src/test/java/org/craftedsw/tripservicekata/trip/TripServiceTest.java

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 0f744130..259a4c7b 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -13,3 +13,4 @@ include:
   - local: "/a-brief-history-of-date/.gitlab-ci.yml"
   - local: "/mustache-replacer/.gitlab-ci.yml"
   - local: "/string-calculator-2/.gitlab-ci.yml"
+  - local: "/trip-service-kata/.gitlab-ci.yml"
diff --git a/README.md b/README.md
index c0518543..ba030d4a 100644
--- a/README.md
+++ b/README.md
@@ -31,5 +31,6 @@ Ce dépôt Git a pour but de partager les différents ateliers pouvant être ré
 | [Une annonce pour recruter un crafter - Caroline, Chloé, Ianic et Colin](https://www.youtube.com/watch?v=E5AX6Ar1Fog) | Discussion  |            |
 | [PadBowl](https://gitlab.com/cdamon/padbowl)                                                                          | Application | Enervé     |
 | [A Brief History of Date](/a-brief-history-of-date)                                                                   | Kata        | Moyenne    |
+| [Trip service (Java)](/trip-service-kata)                                                                             | Kata        | Moyenne    |
 | [Mustache Replacer](/mustache-replacer)                                                                               | Kata        | Facile     |
 | [String calculator 2](/string-calculator-2)                                                                           | Kata        | Moyenne    |
diff --git a/package-lock.json b/package-lock.json
index 6f96882f..b4fba44d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -4,6 +4,18 @@
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
+    "@blakeembrey/deque": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/@blakeembrey/deque/-/deque-1.0.5.tgz",
+      "integrity": "sha512-6xnwtvp9DY1EINIKdTfvfeAtCYw4OqBZJhtiqkT3ivjnEfa25VQ3TsKvaFfKm8MyGIEfE95qLe+bNEt3nB0Ylg==",
+      "dev": true
+    },
+    "@blakeembrey/template": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/@blakeembrey/template/-/template-1.0.0.tgz",
+      "integrity": "sha512-J6WGZqCLdRMHUkyRG6fBSIFJ0rL60/nsQNh5rQvsYZ5u0PsKw6XQcJcA3DWvd9cN3j/IQx5yB1fexhCafwwUUw==",
+      "dev": true
+    },
     "@iamstarkov/listr-update-renderer": {
       "version": "0.4.1",
       "resolved": "https://registry.npmjs.org/@iamstarkov/listr-update-renderer/-/listr-update-renderer-0.4.1.tgz",
@@ -111,6 +123,22 @@
       "integrity": "sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==",
       "dev": true
     },
+    "anymatch": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz",
+      "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==",
+      "dev": true,
+      "requires": {
+        "normalize-path": "^3.0.0",
+        "picomatch": "^2.0.4"
+      }
+    },
+    "arg": {
+      "version": "4.1.3",
+      "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
+      "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
+      "dev": true
+    },
     "argparse": {
       "version": "1.0.10",
       "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
@@ -238,6 +266,12 @@
         }
       }
     },
+    "binary-extensions": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz",
+      "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==",
+      "dev": true
+    },
     "brace-expansion": {
       "version": "1.1.11",
       "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -340,6 +374,57 @@
         "regexp-to-ast": "0.4.0"
       }
     },
+    "chokidar": {
+      "version": "3.4.3",
+      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz",
+      "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==",
+      "dev": true,
+      "requires": {
+        "anymatch": "~3.1.1",
+        "braces": "~3.0.2",
+        "fsevents": "~2.1.2",
+        "glob-parent": "~5.1.0",
+        "is-binary-path": "~2.1.0",
+        "is-glob": "~4.0.1",
+        "normalize-path": "~3.0.0",
+        "readdirp": "~3.5.0"
+      },
+      "dependencies": {
+        "braces": {
+          "version": "3.0.2",
+          "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+          "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+          "dev": true,
+          "requires": {
+            "fill-range": "^7.0.1"
+          }
+        },
+        "fill-range": {
+          "version": "7.0.1",
+          "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+          "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+          "dev": true,
+          "requires": {
+            "to-regex-range": "^5.0.1"
+          }
+        },
+        "is-number": {
+          "version": "7.0.0",
+          "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+          "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+          "dev": true
+        },
+        "to-regex-range": {
+          "version": "5.0.1",
+          "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+          "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+          "dev": true,
+          "requires": {
+            "is-number": "^7.0.0"
+          }
+        }
+      }
+    },
     "class-utils": {
       "version": "0.3.6",
       "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
@@ -839,6 +924,13 @@
       "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
       "dev": true
     },
+    "fsevents": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
+      "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
+      "dev": true,
+      "optional": true
+    },
     "g-status": {
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/g-status/-/g-status-2.0.2.tgz",
@@ -891,6 +983,15 @@
         "path-is-absolute": "^1.0.0"
       }
     },
+    "glob-parent": {
+      "version": "5.1.1",
+      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
+      "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
+      "dev": true,
+      "requires": {
+        "is-glob": "^4.0.1"
+      }
+    },
     "has-ansi": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
@@ -1014,6 +1115,12 @@
         }
       }
     },
+    "ignore": {
+      "version": "5.1.8",
+      "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz",
+      "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==",
+      "dev": true
+    },
     "import-fresh": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz",
@@ -1066,6 +1173,15 @@
       "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
       "dev": true
     },
+    "is-binary-path": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+      "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+      "dev": true,
+      "requires": {
+        "binary-extensions": "^2.0.0"
+      }
+    },
     "is-buffer": {
       "version": "1.1.6",
       "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
@@ -1725,6 +1841,12 @@
         }
       }
     },
+    "normalize-path": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+      "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+      "dev": true
+    },
     "npm-path": {
       "version": "2.0.4",
       "resolved": "https://registry.npmjs.org/npm-path/-/npm-path-2.0.4.tgz",
@@ -1824,6 +1946,64 @@
         "wrappy": "1"
       }
     },
+    "onchange": {
+      "version": "7.0.2",
+      "resolved": "https://registry.npmjs.org/onchange/-/onchange-7.0.2.tgz",
+      "integrity": "sha512-pyJroR9gZKilbJtdGsuyxhFhwaeYSpYVle9hAORGJ5vQQH8n7QT+qWpncJTMEk9dlIXI9tOMjdJwbPaTSPTKFA==",
+      "dev": true,
+      "requires": {
+        "@blakeembrey/deque": "^1.0.5",
+        "@blakeembrey/template": "^1.0.0",
+        "arg": "^4.1.3",
+        "chokidar": "^3.3.1",
+        "cross-spawn": "^7.0.1",
+        "ignore": "^5.1.4",
+        "tree-kill": "^1.2.2"
+      },
+      "dependencies": {
+        "cross-spawn": {
+          "version": "7.0.3",
+          "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+          "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+          "dev": true,
+          "requires": {
+            "path-key": "^3.1.0",
+            "shebang-command": "^2.0.0",
+            "which": "^2.0.1"
+          }
+        },
+        "path-key": {
+          "version": "3.1.1",
+          "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+          "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+          "dev": true
+        },
+        "shebang-command": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+          "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+          "dev": true,
+          "requires": {
+            "shebang-regex": "^3.0.0"
+          }
+        },
+        "shebang-regex": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+          "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+          "dev": true
+        },
+        "which": {
+          "version": "2.0.2",
+          "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+          "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+          "dev": true,
+          "requires": {
+            "isexe": "^2.0.0"
+          }
+        }
+      }
+    },
     "onetime": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
@@ -1899,6 +2079,12 @@
       "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
       "dev": true
     },
+    "picomatch": {
+      "version": "2.2.2",
+      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
+      "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
+      "dev": true
+    },
     "pinkie": {
       "version": "2.0.4",
       "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
@@ -1979,6 +2165,15 @@
         "once": "^1.3.1"
       }
     },
+    "readdirp": {
+      "version": "3.5.0",
+      "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz",
+      "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==",
+      "dev": true,
+      "requires": {
+        "picomatch": "^2.2.1"
+      }
+    },
     "regex-not": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz",
@@ -2457,6 +2652,12 @@
         "repeat-string": "^1.6.1"
       }
     },
+    "tree-kill": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz",
+      "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==",
+      "dev": true
+    },
     "tslib": {
       "version": "1.13.0",
       "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz",
diff --git a/package.json b/package.json
index 6b182484..c66160c0 100644
--- a/package.json
+++ b/package.json
@@ -10,6 +10,7 @@
   "devDependencies": {
     "husky": "1.3.1",
     "lint-staged": "8.1.4",
+    "onchange": "^7.0.2",
     "prettier": "^1.19.1",
     "prettier-plugin-java": "^0.6.0"
   },
diff --git a/trip-service-kata/.gitlab-ci.yml b/trip-service-kata/.gitlab-ci.yml
new file mode 100644
index 00000000..da8e9b1b
--- /dev/null
+++ b/trip-service-kata/.gitlab-ci.yml
@@ -0,0 +1,11 @@
+package-trip-service-kata:
+  variables:
+    PROJECT_FOLDER: "trip-service-kata"
+  extends: .java
+  only:
+    refs:
+      - master
+      - merge_requests
+    changes:
+      - ".gitlab-common-ci.yml"
+      - "trip-service-kata/**/*"
diff --git a/trip-service-kata/pom.xml b/trip-service-kata/pom.xml
new file mode 100644
index 00000000..15e6a48e
--- /dev/null
+++ b/trip-service-kata/pom.xml
@@ -0,0 +1,36 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <version>1.0.0</version>
+        <groupId>fr.ippon.kata</groupId>
+        <artifactId>java-parent</artifactId>
+        <relativePath>../java-parent</relativePath>
+    </parent>
+
+    <version>1.0.0-SNAPSHOT</version>
+    <artifactId>trip-service-kata</artifactId>
+
+    <name>TripServiceKata</name>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-engine</artifactId>
+            <version>5.7.0-M1</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <developers>
+        <developer>
+            <email>jlhermite@ippon.fr</email>
+            <name>Julien LHERMITE</name>
+        </developer>
+        <developer>
+            <email>cdamon@ippon.fr</email>
+            <name>Colin DAMON</name>
+        </developer>
+    </developers>
+</project>
diff --git a/trip-service-kata/readme.md b/trip-service-kata/readme.md
new file mode 100644
index 00000000..2b12a4e6
--- /dev/null
+++ b/trip-service-kata/readme.md
@@ -0,0 +1,32 @@
+# Trip service (java)
+
+Découverte et résolution du kata [TripService](https://github.com/sandromancuso/trip-service-kata)
+
+-   **Auteur** : Julien LHERMITE et Colin DAMON
+-   **Date** : 20/10/2020
+-   **Langage** : Java
+-   **Niveau** : Moyen
+-   **Replay** : [Trip Service Kata (Java) avec Julien & Colin](https://www.youtube.com/watch?v=YIKI_-xqJfc)
+
+# Testing legacy code: Hard-wired dependencies
+
+Code related to my [Testing legacy code: Hard-wired dependencies][1] blog post. Try not reading the blog post before doing the exercise yourself.
+
+## What is it about?
+
+Provides an example of existing code that needs to be unit tested. But there is one rule:
+
+> We can't change any existing code if not covered by tests. The only exception is if we need to change the code to add unit tests, but in this case, just automated refactorings (via IDE) are allowed.
+
+Although this is a very small piece of code, it has a lot of the problems that we find in legacy code.
+
+## Details
+
+If you want to give it a go, the starting point is [TripServiceTest.java][3] and [TripService.java][4]. Try unit testing it following the rule above.
+
+For future comparisions, when you are done, you can always check [TripService_Original.java][2]
+
+[1]: http://codurance.com/2011/07/16/testing-legacy-hard-wired-dependencies/ "Testing legacy code: Hard-wired dependencies blog post"
+[2]: https://github.com/sandromancuso/trip-service-kata/blob/master/java/trip-service-kata/src/main/java/org/craftedsw/tripservicekata/TripService_Original.java "TripService_Original.java"
+[3]: https://github.com/sandromancuso/trip-service-kata/blob/master/java/trip-service-kata/src/test/java/org/craftedsw/tripservicekata/TripServiceTest.java "TripServiceTest.java"
+[4]: https://github.com/sandromancuso/trip-service-kata/blob/master/java/trip-service-kata/src/main/java/org/craftedsw/tripservicekata/trip/TripService.java "TripService.java"
diff --git a/trip-service-kata/src/main/java/org/craftedsw/tripservicekata/TripService_Original.java b/trip-service-kata/src/main/java/org/craftedsw/tripservicekata/TripService_Original.java
new file mode 100644
index 00000000..a2ba5ee3
--- /dev/null
+++ b/trip-service-kata/src/main/java/org/craftedsw/tripservicekata/TripService_Original.java
@@ -0,0 +1,34 @@
+package org.craftedsw.tripservicekata;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.craftedsw.tripservicekata.exception.UserNotLoggedInException;
+import org.craftedsw.tripservicekata.trip.Trip;
+import org.craftedsw.tripservicekata.trip.TripDAO;
+import org.craftedsw.tripservicekata.user.User;
+import org.craftedsw.tripservicekata.user.UserSession;
+
+public class TripService_Original {
+
+	public List<Trip> getTripsByUser(User user) throws UserNotLoggedInException {
+		List<Trip> tripList = new ArrayList<Trip>();
+		User loggedUser = UserSession.getInstance().getLoggedUser();
+		boolean isFriend = false;
+		if (loggedUser != null) {
+			for (User friend : user.getFriends()) {
+				if (friend.equals(loggedUser)) {
+					isFriend = true;
+					break;
+				}
+			}
+			if (isFriend) {
+				tripList = TripDAO.findTripsByUser(user);
+			}
+			return tripList;
+		} else {
+			throw new UserNotLoggedInException();
+		}
+	}
+	
+}
diff --git a/trip-service-kata/src/main/java/org/craftedsw/tripservicekata/exception/CollaboratorCallException.java b/trip-service-kata/src/main/java/org/craftedsw/tripservicekata/exception/CollaboratorCallException.java
new file mode 100644
index 00000000..828353e7
--- /dev/null
+++ b/trip-service-kata/src/main/java/org/craftedsw/tripservicekata/exception/CollaboratorCallException.java
@@ -0,0 +1,25 @@
+package org.craftedsw.tripservicekata.exception;
+
+public class CollaboratorCallException extends RuntimeException {
+
+	private static final long serialVersionUID = -4584041339906109902L;
+
+	public CollaboratorCallException() {
+		super();
+	}
+
+	public CollaboratorCallException(String message,
+			Throwable cause) {
+		super(message, cause);
+	}
+
+	public CollaboratorCallException(String message) {
+		super(message);
+	}
+
+	public CollaboratorCallException(Throwable cause) {
+		super(cause);
+	}
+
+	
+}
diff --git a/trip-service-kata/src/main/java/org/craftedsw/tripservicekata/exception/UserNotLoggedInException.java b/trip-service-kata/src/main/java/org/craftedsw/tripservicekata/exception/UserNotLoggedInException.java
new file mode 100644
index 00000000..880bf204
--- /dev/null
+++ b/trip-service-kata/src/main/java/org/craftedsw/tripservicekata/exception/UserNotLoggedInException.java
@@ -0,0 +1,7 @@
+package org.craftedsw.tripservicekata.exception;
+
+public class UserNotLoggedInException extends RuntimeException {
+
+	private static final long serialVersionUID = 8959479918185637340L;
+
+}
diff --git a/trip-service-kata/src/main/java/org/craftedsw/tripservicekata/trip/Trip.java b/trip-service-kata/src/main/java/org/craftedsw/tripservicekata/trip/Trip.java
new file mode 100644
index 00000000..f12ff3cc
--- /dev/null
+++ b/trip-service-kata/src/main/java/org/craftedsw/tripservicekata/trip/Trip.java
@@ -0,0 +1,5 @@
+package org.craftedsw.tripservicekata.trip;
+
+public class Trip {
+
+}
diff --git a/trip-service-kata/src/main/java/org/craftedsw/tripservicekata/trip/TripDAO.java b/trip-service-kata/src/main/java/org/craftedsw/tripservicekata/trip/TripDAO.java
new file mode 100644
index 00000000..8c5c5d4d
--- /dev/null
+++ b/trip-service-kata/src/main/java/org/craftedsw/tripservicekata/trip/TripDAO.java
@@ -0,0 +1,17 @@
+package org.craftedsw.tripservicekata.trip;
+
+import java.util.List;
+import org.craftedsw.tripservicekata.exception.CollaboratorCallException;
+import org.craftedsw.tripservicekata.user.User;
+
+public class TripDAO implements Trips {
+
+  public static List<Trip> findTripsByUser(User user) {
+    throw new CollaboratorCallException("TripDAO should not be invoked on an unit test.");
+  }
+
+  @Override
+  public List<Trip> find(User user) {
+    return TripDAO.findTripsByUser(user);
+  }
+}
diff --git a/trip-service-kata/src/main/java/org/craftedsw/tripservicekata/trip/TripService.java b/trip-service-kata/src/main/java/org/craftedsw/tripservicekata/trip/TripService.java
new file mode 100644
index 00000000..00ea2883
--- /dev/null
+++ b/trip-service-kata/src/main/java/org/craftedsw/tripservicekata/trip/TripService.java
@@ -0,0 +1,39 @@
+package org.craftedsw.tripservicekata.trip;
+
+import java.util.List;
+import org.craftedsw.tripservicekata.exception.UserNotLoggedInException;
+import org.craftedsw.tripservicekata.user.User;
+import org.craftedsw.tripservicekata.user.UserSession;
+
+public class TripService {
+  private final UserSession userSession;
+  private final Trips trips;
+
+  public TripService(UserSession userSession, Trips trips) {
+    this.userSession = userSession;
+    this.trips = trips;
+  }
+
+  public List<Trip> getTripsByUser(User user) throws UserNotLoggedInException {
+    User loggedUser = userSession.getLoggedUser();
+    assertUserIsAuthenticated(loggedUser);
+
+    return user
+      .getFriends()
+      .stream()
+      .filter(friend -> friend.equals(loggedUser))
+      .findFirst()
+      .map(friend -> findTrips(user))
+      .orElse(List.of());
+  }
+
+  protected List<Trip> findTrips(User user) {
+    return trips.find(user);
+  }
+
+  private void assertUserIsAuthenticated(User loggedUser) {
+    if (loggedUser == null) {
+      throw new UserNotLoggedInException();
+    }
+  }
+}
diff --git a/trip-service-kata/src/main/java/org/craftedsw/tripservicekata/trip/Trips.java b/trip-service-kata/src/main/java/org/craftedsw/tripservicekata/trip/Trips.java
new file mode 100644
index 00000000..66e97d16
--- /dev/null
+++ b/trip-service-kata/src/main/java/org/craftedsw/tripservicekata/trip/Trips.java
@@ -0,0 +1,8 @@
+package org.craftedsw.tripservicekata.trip;
+
+import java.util.List;
+import org.craftedsw.tripservicekata.user.User;
+
+public interface Trips {
+  List<Trip> find(User user);
+}
diff --git a/trip-service-kata/src/main/java/org/craftedsw/tripservicekata/user/User.java b/trip-service-kata/src/main/java/org/craftedsw/tripservicekata/user/User.java
new file mode 100644
index 00000000..cafaa200
--- /dev/null
+++ b/trip-service-kata/src/main/java/org/craftedsw/tripservicekata/user/User.java
@@ -0,0 +1,29 @@
+package org.craftedsw.tripservicekata.user;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.craftedsw.tripservicekata.trip.Trip;
+
+public class User {
+
+	private List<Trip> trips = new ArrayList<Trip>();
+	private List<User> friends = new ArrayList<User>();
+	
+	public List<User> getFriends() {
+		return friends;
+	}
+	
+	public void addFriend(User user) {
+		friends.add(user);
+	}
+
+	public void addTrip(Trip trip) {
+		trips.add(trip);
+	}
+	
+	public List<Trip> trips() {
+		return trips;
+	}
+
+}
diff --git a/trip-service-kata/src/main/java/org/craftedsw/tripservicekata/user/UserSession.java b/trip-service-kata/src/main/java/org/craftedsw/tripservicekata/user/UserSession.java
new file mode 100644
index 00000000..6b91c0d8
--- /dev/null
+++ b/trip-service-kata/src/main/java/org/craftedsw/tripservicekata/user/UserSession.java
@@ -0,0 +1,21 @@
+package org.craftedsw.tripservicekata.user;
+
+import org.craftedsw.tripservicekata.exception.CollaboratorCallException;
+
+public class UserSession {
+
+	private static final UserSession userSession = new UserSession();
+	
+	private UserSession() {
+	}
+	
+	public static UserSession getInstance() {
+		return userSession;
+	}
+
+	public User getLoggedUser() {
+		throw new CollaboratorCallException(
+				"UserSession.getLoggedUser() should not be called in an unit test");
+	}
+
+}
diff --git a/trip-service-kata/src/test/java/org/craftedsw/tripservicekata/trip/TripDAOTest.java b/trip-service-kata/src/test/java/org/craftedsw/tripservicekata/trip/TripDAOTest.java
new file mode 100644
index 00000000..36f1e09d
--- /dev/null
+++ b/trip-service-kata/src/test/java/org/craftedsw/tripservicekata/trip/TripDAOTest.java
@@ -0,0 +1,3 @@
+package org.craftedsw.tripservicekata.trip;
+
+class TripDAOTest {}
diff --git a/trip-service-kata/src/test/java/org/craftedsw/tripservicekata/trip/TripServiceTest.java b/trip-service-kata/src/test/java/org/craftedsw/tripservicekata/trip/TripServiceTest.java
new file mode 100644
index 00000000..f22c1990
--- /dev/null
+++ b/trip-service-kata/src/test/java/org/craftedsw/tripservicekata/trip/TripServiceTest.java
@@ -0,0 +1,61 @@
+package org.craftedsw.tripservicekata.trip;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.mockito.Mockito.when;
+
+import java.util.List;
+import org.craftedsw.tripservicekata.exception.UserNotLoggedInException;
+import org.craftedsw.tripservicekata.user.User;
+import org.craftedsw.tripservicekata.user.UserSession;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+@ExtendWith(MockitoExtension.class)
+class TripServiceTest {
+  private final User authenticatedUser = new User();
+
+  private final User friend = new User();
+
+  @Mock
+  private UserSession userSession;
+
+  @Mock
+  private Trips trips;
+
+  @InjectMocks
+  private TripService service;
+
+  @BeforeEach
+  void loadAuthentication() {
+    when(userSession.getLoggedUser()).thenReturn(authenticatedUser);
+  }
+
+  @Test
+  void shouldNotGetTripsWithoutAuthenticatedUser() {
+    when(userSession.getLoggedUser()).thenReturn(null);
+
+    assertThatThrownBy(() -> service.getTripsByUser(authenticatedUser)).isExactlyInstanceOf(UserNotLoggedInException.class);
+  }
+
+  @Test
+  void shouldGetEmptyTripsForNewUser() {
+    assertThat(service.getTripsByUser(authenticatedUser)).isEmpty();
+  }
+
+  @Test
+  void shouldGetFriendTrips() {
+    friend.addFriend(authenticatedUser);
+
+    Trip tripToLasVegas = new Trip();
+    friend.addTrip(tripToLasVegas);
+
+    when(trips.find(friend)).thenReturn(List.of(tripToLasVegas));
+
+    assertThat(service.getTripsByUser(friend)).containsExactly(tripToLasVegas);
+  }
+}
-- 
GitLab