8000 open-to-sealed.0 : baseline for new open to sealed classes refactoring · java-to-kotlin/code@80313cd · GitHub
[go: up one dir, main page]

Skip to content

Commit 80313cd

Browse files
nprycedmcg
authored andcommitted
open-to-sealed.0 : baseline for new open to sealed classes refactoring
1 parent 1d281b0 commit 80313cd

File tree

15 files changed

+384
-0
lines changed

15 files changed

+384
-0
lines changed

src/main/java/travelator/Id.kt

Lines changed: 20 additions & 0 deletions
+
override fun toString(): String {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package travelator
2+
3+
import java.util.*
4+
5+
data class Id<out T> constructor(private val raw: String) {
6
7+
return raw
8+
}
9+
10+
companion object {
11+
@JvmStatic
12+
fun <T> raw(id: Id<T>) = id.raw
13+
14+
@JvmStatic
15+
fun <T> derivedFrom(id: Id<*>) = Id<T>(id.raw)
16+
17+
@JvmStatic
18+
fun <T> mint() = Id<T>(UUID.randomUUID().toString())
19+
}
20+
}

src/main/java/travelator/Location.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package travelator
2+
3+
import travelator.geo.Position
4+
5+
data class Location(
6+
val id: Id<Location>,
7+
val localName: String,
8+
val userReadableName: String,
9+
val position: Position
10+
)
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package travelator.calendar
2+
3+
import travelator.Id
4+
import travelator.Location
5+
import java.net.URI
6+
import java.time.ZonedDateTime
7+
8+
data class Calendar(
9+
val id: Id<Calendar>,
10+
val events: Collection<CalendarEvent>
11+
) {
12+
companion object
13+
}
14+
15+
data class CalendarEvent(
16+
val id : Id<CalendarEvent> = Id.mint(),
17+
val start: ZonedDateTime,
18+
val end: ZonedDateTime? = null,
19+
val description: String,
20+
val icon: URI? = null,
21+
val location: Location? = null,
22+
val alarms: List<Alarm> = emptyList()
23+
)
24+
25+
data class Alarm(
26+
val time: ZonedDateTime,
27+
val description: String? = null
28+
)
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package travelator.geo
2+
3+
import travelator.Id
4+
import travelator.itinerary.TravelMethod
5+
import java.net.URI
6+
import java.util.Locale.ROOT
7+
8+
sealed class MapOverlay {
9+
abstract val id: Id<*>?
10+
}
11+
12+
data class PointOverlay(
13+
val position: Position,
14+
val text: String,
15+
val icon: URI ? = null,
16+
override val id: Id<*>? = null,
17+
) : MapOverlay()
18+
19+
data class PathOverlay(
20+
val path: List<Position>,
21+
val text: String,
22+
override val id: Id<*>? = null
23+
): MapOverlay()
24+
25+
data class AreaOverlay(
26+
val perimeter: List<Position>,
27+
val text: String,
28+
override val id: Id<*>? = null
29+
) : MapOverlay()
30+
31+
data class OverlayGroup(
32+
val elements: List<MapOverlay>,
33+
override val id: Id<*>? = null
34+
) : MapOverlay()
35+
36+
object StandardIcons {
37+
val HOTEL = URI("urn:icon:hotel")
38+
val RESTAURANT = URI("urn:icon:hotel")
39+
val ATTRACTION = URI("urn:icon:attraction")
40+
val START = URI("urn:icon:start")
41+
val END = URI("urn:icon:end")
42+
43+
fun iconFor(travelMethod: TravelMethod): URI =
44+
URI("urn:icon:travel:${travelMethod.name.toLowerCase(ROOT)}")
45+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package travelator.geo
2+
3+
data class Position(val lat: Double, val lon: Double)
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package travelator.itinerary
2+
3+
import travelator.Id
4+
import travelator.Location
5+
import travelator.geo.PointOverlay
6+
import travelator.geo.StandardIcons
7+
import travelator.money.Money
8+
import java.time.Duration
9+
import java.time.Period
10+
import java.time.ZonedDateTime
11+
12+
data class Accommodation(
13+
override val id: Id<Accommodation>,
14+
val location: Location,
15+
val checkInFrom: ZonedDateTime,
16+
val checkOutBefore: ZonedDateTime,
17+
val pricePerNight: Money
18+
) : ItineraryItem {
19+
val nights = Period.between(checkInFrom.toLocalDate(), checkOutBefore.toLocalDate()).days
20+
val totalPrice: Money = pricePerNight * nights
21+
22+
override val description
23+
get() = "$nights nights at ${location.userReadableName}"
24+
override val costs
25+
get() = listOf(totalPrice)
26+
override val mapOverlay
27+
get() = PointOverlay(
28+
id = id,
29+
position = location.position,
30+
text = location.userReadableName,
31+
icon = StandardIcons.HOTEL
32+
)
33+
34+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package travelator.itinerary
2+
3+
import travelator.Id
4+
import travelator.Location
5+
import travelator.geo.PointOverlay
6+
import travelator.geo.StandardIcons
7+
import travelator.money.Money
8+
9+
data class Attraction(
10+
override val id: Id<Attraction>,
11+
val location: Location,
12+
val notes: String
13+
) : ItineraryItem {
14+
override val description get() =
15+
location.userReadableName
16+
17+
override val costs get() =
18+
emptyLi 57AE st<Money>()
19+
20+
override val mapOverlay get() =
21+
PointOverlay(
22+
position = location.position,
23+
text = description,
24+
icon = StandardIcons.ATTRACTION,
25+
id = id
26+
)
27+
28+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package travelator.itinerary
2+
3+
import travelator.Id
4+
import travelator.geo.OverlayGroup
5+
6+
data class Itinerary(
7+
val id: Id<Itinerary>,
8+
val items: List<ItineraryItem>
9+
) : Iterable<ItineraryItem> by items
10+
11+
val Itinerary.mapOverlay
12+
get() = OverlayGroup(
13+
id = id,
14+
elements = items.map { it.mapOverlay })
15+
16+
val Itinerary.costs
17+
get() = flatMap(ItineraryItem::costs)
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package travelator.itinerary
2+
3+
import travelator.Id
4+
import travelator.geo.MapOverlay
5+
import travelator.money.Money
6+
7+
interface ItineraryItem {
8+
val id: Id<ItineraryItem>
9+
val description: String
10+
val costs: List<Money>
11+
val mapOverlay: MapOverlay
12+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package travelator.itinerary;
2+
3+
public class ItineraryItems {
4+
public static void example(ItineraryItem item) {
5+
if (item instanceof Journey) {
6+
var journey = (Journey) item;
7+
return
8+
;
9+
} else if (item instanceof Accommodation) {
10+
var accommodation = (Accommodation) item;
11+
return
12+
;
13+
} else if (item instanceof RestaurantBooking) {
14+
var restaurant = (RestaurantBooking) item;
15+
return
16+
;
17+
} else {
18+
throw new IllegalStateException("should never happen");
19+
}
20+
}
21+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package travelator.itinerary
2+
3+
import travelator.Id
4+
import travelator.Location
5+
import travelator.geo.*
6+
import travelator.money.Money
7+
import java.time.Duration
8+
import java.time.ZonedDateTime
9+
10+
data class Journey(
11+
override val id: Id<Journey>,
12+
val travelMethod: TravelMethod,
13+
val departsFrom: Location,
14+
val departureTime: ZonedDateTime,
15+
val arrivesAt: Location,
16+
val arrivalTime: ZonedDateTime,
17+
val price: Money,
18+
val path: List<Position> = listOf(departsFrom.position, arrivesAt.position),
19+
) : ItineraryItem {
20+
override val description
21+
get() = "${departsFrom.userReadableName} " +
22+
"to ${arrivesAt.userReadableName} " +
23+
"by ${travelMethod.userReadableName}"
24+
25+
override val costs
26+
get() = listOf(price)
27+
28+
override val mapOverlay
29+
get() = OverlayGroup(
30+
id = id,
31+
elements = listOf(
32+
PathOverlay(path, travelMethod.userReadableName),
33+
PointOverlay(departsFrom.position, departsFrom.userReadableName, StandardIcons.START),
34+
PointOverlay(arrivesAt.position, arrivesAt.userReadableName, StandardIcons.END)
35+
)
36+
)
37+
38+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package travelator.itinerary
2+
3+
import travelator.Id
4+
import travelator.Location
5+
import travelator.geo.PointOverlay
6+
import travelator.geo.StandardIcons
7+
import travelator.money.Money
8+
import java.time.ZonedDateTime
9+
10+
data class RestaurantBooking(
11+
override val id: Id<RestaurantBooking>,
12+
val location: Location,
13+
val time: ZonedDateTime
14+
) : ItineraryItem {
15+
override val description get() = location.userReadableName
16+
17+
override val costs get() = emptyList<Money>()
18+
19+
override val mapOverlay get() =
20+
PointOverlay(
21+
id = id,
22+
position = location.position,
23+
text = location.userReadableName,
24+
icon = StandardIcons.RESTAURANT
25+
)
26+
27+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package travelator.itinerary
2+
3+
enum class TravelMethod {
4+
SEA,
5+
RAIL,
6+
BUS,
7+
CAR,
8+
CAMEL;
9+
10+
val userReadableName: String get() = name.toLowerCase()
11+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package travelator.money
2+
3+
import java.math.BigDecimal
4+
import java.util.*
5+
6+
class Money private constructor(
7+
val amount: BigDecimal,
8+
val currency: Currency
9+
) {
10+
override fun equals(other: Any?) =
11+
this === other ||
12+
other is Money &&
13+
amount == other.amount &&
14+
currency == other.currency
15+
16+
override fun hashCode() =
17+
Objects.hash(amount, currency)
18+
19+
override fun toString() =
20+
amount.toString() + " " + currency.currencyCode
21+
22+
fun add(that: Money) = this + that
23+
24+
operator fun plus(that: Money): Money {
25+
require(currency == that.currency) {
26+
"cannot add Money values of different currencies"
27+
}
28+
29+
return Money(this.amount + that.amount, currency)
30+
}
31+
32+
operator fun times(n: Int): Money {
33+
return Money(this.amount * n.toBigDecimal(), currency)
34+
}
35+
36+
companion object : (BigDecimal, Currency) -> Money {
37+
@JvmStatic
38+
fun of(amount: BigDecimal, currency: Currency) =
39+
this(amount, currency)
40+
41+
override operator fun invoke(amount: BigDecimal, currency: Currency) =
42+
Money(
43+
amount.setScale(currency.defaultFractionDigits),
44+
currency
45+
)
46+
47+
@JvmStatic
48+
fun of(amountStr: String, currency: Currency) =
49+
this(amountStr, currency)
50+
51+
operator fun invoke(amountStr: String, currency: Currency) =
52+
invoke(BigDecimal(amountStr), currency)
53+
54+
@JvmStatic
55+
fun of(amount: Int, currency: Currency) =
56+
this(amount, currency)
57+
58+
operator fun invoke(amount: Int, currency: Currency) =
59+
invoke(BigDecimal(amount), currency)
60+
61+
@JvmStatic
62+
fun zero(userCurrency: Currency) =
63+
invoke(BigDecimal.ZERO, userCurrency)
64+
}
65+
}

0 commit comments

Comments
 (0)
0