Skip to content

Commit 611cc05

Browse files
committed
add additional examples, finalise Kotlin parts
1 parent af0fd15 commit 611cc05

File tree

11 files changed

+368
-143
lines changed

11 files changed

+368
-143
lines changed

app-kotlin/src/ch/bfh/cssem/kotlin/app/kotlin/ApiExtensions/Extensions.kt

+5-6
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,20 @@ package ch.bfh.cssem.kotlin.app.kotlin.ApiExtensions
33
import ch.bfh.cssem.kotlin.api.AddressBook
44
import ch.bfh.cssem.kotlin.api.City
55
import ch.bfh.cssem.kotlin.api.State
6+
import ch.bfh.cssem.kotlin.app.kotlin.splitPair
67

78
/**
89
* Alternative to [AddressBook.fetchCityByPostalCodeName] taking one parameter instead.
910
*/
1011
fun AddressBook.fetchCityByPostalCodeName(postalCodeName: String): City? {
11-
val abbrs = postalCodeName.split('-')
12-
if (abbrs.size != 2) throw IllegalArgumentException("There must be both the postal code and the name separated by a dash.")
13-
return fetchCityByPostalCodeName(abbrs[0], abbrs[1])
12+
val (postalCode, name) = postalCodeName.splitPair('-')
13+
return fetchCityByPostalCodeName(postalCode, name)
1414
}
1515

1616
/**
1717
* Alternative to [AddressBook.fetchStateByAbbreviation] taking one parameter instead.
1818
*/
1919
fun AddressBook.fetchStateByAbbreviation(countryStateAbbreviation: String): State? {
20-
val abbrs = countryStateAbbreviation.split('-')
21-
if (abbrs.size != 2) throw IllegalArgumentException("There must be both the country and the state abbreviation separated by a dash.")
22-
return fetchStateByAbbreviation(abbrs[0], abbrs[1])
20+
val (countryAbbreviation, abbreviation) = countryStateAbbreviation.splitPair('-')
21+
return fetchStateByAbbreviation(countryAbbreviation, abbreviation)
2322
}

app-kotlin/src/ch/bfh/cssem/kotlin/app/kotlin/ApiExtensions/FXCity.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import ch.bfh.cssem.kotlin.api.City
55
/**
66
* Special JavaFX implementation of the interface [City].
77
*
8-
* @property impl concrete implementation of the interface
8+
* @property implementation concrete implementation of the interface
99
* @property stateAbbreviation the state's abbreviation
1010
* @property stateName the state's name
1111
* @property countryAbbreviation the country's abbreviation
@@ -14,7 +14,7 @@ import ch.bfh.cssem.kotlin.api.City
1414
*
1515
* @author strut1 & touwm1
1616
*/
17-
class FXCity(val impl: City) : City by impl {
17+
class FXCity(val implementation: City) : City by implementation {
1818

1919
val stateAbbreviation: String?
2020
get() = state?.abbreviation

app-kotlin/src/ch/bfh/cssem/kotlin/app/kotlin/ApiExtensions/FXCountry.kt

+4-4
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@ import ch.bfh.cssem.kotlin.api.Country
55
/**
66
* Special JavaFX implementation of the interface [Country].
77
*
8-
* @property impl concrete implementation of the interface
9-
* @property nofCities the number of cities in this country
10-
* @property nofStates the number of states in this country
8+
* @property implementation concrete implementation of the interface
9+
* @property nofCities the number of cities in this country
10+
* @property nofStates the number of states in this country
1111
*
1212
* @author strut1 & touwm1
1313
*/
14-
class FXCountry(val impl: Country) : Country by impl {
14+
class FXCountry(val implementation: Country) : Country by implementation {
1515

1616
val nofCities: Int
1717
get() = cities.size

app-kotlin/src/ch/bfh/cssem/kotlin/app/kotlin/ApiExtensions/FXPerson.kt

+80-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import ch.bfh.cssem.kotlin.api.State
77
/**
88
* Special JavaFX implementation of the interface [Person].
99
*
10-
* @property impl concrete implementation of the interface
10+
* @property implementation concrete implementation of the interface
1111
* @property cityPostalCode the city's postal code
1212
* @property cityName the city's name
1313
* @property cityState the city's state
@@ -22,7 +22,7 @@ import ch.bfh.cssem.kotlin.api.State
2222
*
2323
* @author strut1 & touwm1
2424
*/
25-
class FXPerson(val impl: Person) : Person by impl {
25+
open class FXPerson(val implementation: Person) : Person by implementation {
2626

2727
val cityPostalCode: String?
2828
get() = city?.postalCode
@@ -48,7 +48,7 @@ class FXPerson(val impl: Person) : Person by impl {
4848
val cityCountryName: String?
4949
get() = cityCountry?.name
5050

51-
val address: String?
51+
open val address: String?
5252
get() {
5353
if (street === null && city === null)
5454
return null
@@ -77,3 +77,80 @@ class FXPerson(val impl: Person) : Person by impl {
7777
val phone: String?
7878
get() = listOf(phoneHome, phoneMobile, phoneWork).filter { it !== null && it.length > 0 }.joinToString(separator = " / ")
7979
}
80+
81+
sealed class FXPersonI18n(implementation: Person) : FXPerson(implementation) {
82+
83+
class CH(implementation: Person) : FXPersonI18n(implementation)
84+
85+
class AT(implementation: Person) : DE(implementation)
86+
class FR(implementation: Person) : DE(implementation, true)
87+
open class DE(implementation: Person, val upperCaseCity: Boolean = false) : FXPersonI18n(implementation) {
88+
89+
override val address: String?
90+
get() {
91+
if (street === null && city === null)
92+
return null
93+
94+
val city = this.city //enable smart cast
95+
96+
val sb = StringBuilder()
97+
if (street !== null) {
98+
sb.append(street)
99+
if (city !== null) sb.append(", ")
100+
}
101+
if (city !== null)
102+
sb.append(city.postalCode).append(' ').append(if (upperCaseCity) city.name.toUpperCase() else city.name)
103+
104+
return sb.toString()
105+
}
106+
}
107+
108+
class UK(implementation: Person) : FXPersonI18n(implementation) {
109+
110+
override val address: String?
111+
get() {
112+
if (street === null && city === null)
113+
return null
114+
115+
val city = this.city //enable smart cast
116+
117+
val sb = StringBuilder()
118+
if (street !== null) {
119+
sb.append(street)
120+
if (city !== null) sb.append(", ")
121+
}
122+
if (city !== null)
123+
sb.append(city.name).append(", ").append(city.postalCode)
124+
125+
return sb.toString()
126+
}
127+
}
128+
129+
class US_USPS(implementation: Person) : US(implementation, true)
130+
open class US(implementation: Person, val upperCase: Boolean = false) : FXPersonI18n(implementation) {
131+
132+
override val address: String?
133+
get() {
134+
if (street === null && city === null)
135+
return null
136+
137+
val street = this.street //enable smart cast
138+
val city = this.city
139+
val state = city?.state
140+
141+
val sb = StringBuilder()
142+
if (street !== null) {
143+
sb.append(if (upperCase) street.toUpperCase() else street)
144+
if (city !== null) sb.append(", ")
145+
}
146+
if (city !== null) {
147+
sb.append(if (upperCase) city.name.toUpperCase() else city.name).append(", ")
148+
if (state !== null )
149+
sb.append(state.abbreviation).append(' ')
150+
sb.append(city.postalCode)
151+
}
152+
153+
return sb.toString()
154+
}
155+
}
156+
}

app-kotlin/src/ch/bfh/cssem/kotlin/app/kotlin/ApiExtensions/FXState.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ import ch.bfh.cssem.kotlin.api.State
55
/**
66
* Special JavaFX implementation of the interface [State].
77
*
8-
* @property impl concrete implementation of the interface
8+
* @property implementation concrete implementation of the interface
99
* @property countryAbbreviation the country's abbreviation
1010
* @property countryName the country's name
1111
* @property nofCities the number of cities in this state
1212
*
1313
* @author strut1 & touwm1
1414
*/
15-
class FXState(val impl: State) : State by impl {
15+
class FXState(val implementation: State) : State by implementation {
1616

1717
val countryAbbreviation: String
1818
get() = country.abbreviation

app-kotlin/src/ch/bfh/cssem/kotlin/app/kotlin/Extensions.kt

+100
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,103 @@ infix fun <T> List<T>.intersectList(other: List<T>): List<T> {
88
mut.retainAll(other)
99
return mut
1010
}
11+
12+
//infix fun <T> List<T>.intersectList(other: List<T>): List<T> {
13+
// val intersection = arrayListOf<T>()
14+
// for (element in this)
15+
// if (element in other) intersection.add(element)
16+
// return intersection
17+
//}
18+
19+
/**
20+
* Turns a list into a pair.
21+
*/
22+
fun <T> List<T>.makePair(): Pair<T, T> = if (size == 2) Pair(get(0), get(1)) else throw IllegalArgumentException("There must be exactly two elements to make a pair.")
23+
24+
/**
25+
* Turns a list into a triple.
26+
*/
27+
fun <T> List<T>.makeTriple(): Triple<T, T, T> = if (size == 3) Triple(get(0), get(1), get(2)) else throw IllegalArgumentException("There must be exactly three elements to make a triple.")
28+
29+
/**
30+
* Splits a string in two.
31+
*
32+
* @param delimiters One or more strings to be used as delimiters.
33+
* @param ignoreCase `true` to ignore character case when matching a delimiter. By default `false`.
34+
* @param limit The maximum number of substrings to return. Zero by default means no limit is set.
35+
*/
36+
fun CharSequence.splitPair(vararg delimiters: String, ignoreCase: Boolean = false, limit: Int = 0) = split(*delimiters, ignoreCase = ignoreCase, limit = limit).makePair()
37+
38+
/**
39+
* Splits a string in two.
40+
*
41+
* @param delimiters One or more characters to be used as delimiters.
42+
* @param ignoreCase `true` to ignore character case when matching a delimiter. By default `false`.
43+
* @param limit The maximum number of substrings to return.
44+
*/
45+
fun CharSequence.splitPair(vararg delimiters: Char, ignoreCase: Boolean = false, limit: Int = 0) = split(*delimiters, ignoreCase = ignoreCase, limit = limit).makePair()
46+
47+
/**
48+
* Splits a string in two.
49+
*
50+
* @param limit Non-negative value specifying the maximum number of substrings to return.
51+
*/
52+
fun CharSequence.splitPair(regex: Regex, limit: Int = 0) = split(regex, limit).makePair()
53+
54+
/**
55+
* Splits a string in three.
56+
*
57+
* @param delimiters One or more strings to be used as delimiters.
58+
* @param ignoreCase `true` to ignore character case when matching a delimiter. By default `false`.
59+
* @param limit The maximum number of substrings to return. Zero by default means no limit is set.
60+
*/
61+
fun CharSequence.splitTriple(vararg delimiters: String, ignoreCase: Boolean = false, limit: Int = 0) = split(*delimiters, ignoreCase = ignoreCase, limit = limit).makeTriple()
62+
63+
/**
64+
* Splits a string in three.
65+
*
66+
* @param delimiters One or more characters to be used as delimiters.
67+
* @param ignoreCase `true` to ignore character case when matching a delimiter. By default `false`.
68+
* @param limit The maximum number of substrings to return.
69+
*/
70+
fun CharSequence.splitTriple(vararg delimiters: Char, ignoreCase: Boolean = false, limit: Int = 0) = split(*delimiters, ignoreCase = ignoreCase, limit = limit).makeTriple()
71+
72+
/**
73+
* Splits a string in three.
74+
*
75+
* @param limit Non-negative value specifying the maximum number of substrings to return.
76+
*/
77+
fun CharSequence.splitTriple(regex: Regex, limit: Int = 0) = split(regex, limit).makeTriple()
78+
79+
/**
80+
* Creates a predicate that represents the logical negation of this predicate.
81+
*/
82+
fun <T> ((T) -> Boolean).negate() = { t: T -> !this(t) }
83+
84+
/**
85+
* Creates a composed predicate that represents a short-circuiting logical AND of this predicate and another.
86+
*
87+
* @param other the other predicate to use
88+
*/
89+
fun <T> ((T) -> Boolean).and(other: (T) -> Boolean) = { t: T -> this(t) && other(t) }
90+
91+
/**
92+
* Creates a composed predicate that represents a short-circuiting logical OR of this predicate and another.
93+
*
94+
* @param other the other predicate to use
95+
*/
96+
fun <T> ((T) -> Boolean).or(other: (T) -> Boolean) = { t: T -> this(t) || other(t) }
97+
98+
/**
99+
* Tries to parse a string to an integer number.
100+
* Returns null if parsing failed.
101+
*/
102+
fun String.tryToInt(): Int? {
103+
104+
return try {
105+
toInt()
106+
107+
} catch(ex: NumberFormatException) {
108+
null
109+
}
110+
}

app-kotlin/src/ch/bfh/cssem/kotlin/app/kotlin/SearchFilter.kt

+18-6
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,28 @@ data class SearchFilter(var valueFilters: MutableMap<String, String>, var textFi
2121
internal const val cityKey = "city"
2222
internal const val stateKey = "state"
2323
internal const val countryKey = "country"
24+
25+
/**
26+
* Creates a [SearchFilter] from the filter text.
27+
*
28+
* @param string [String] to create filter from
29+
*/
30+
fun makeFilter(string: String): SearchFilter {
31+
val regex = Regex("\\s*\\[\\s*(\\w+)\\s*=\\s*([^\\]]+)\\s*\\]\\s*")
32+
val map = hashMapOf<String, String>()
33+
regex.findAll(string).forEach { map.put(it.groups[1]!!.value, it.groups[2]!!.value) }
34+
return SearchFilter(map, regex.replace(string, ""))
35+
}
2436
}
2537
}
2638

2739
/**
2840
* Creates a [SearchFilter] from the filter text.
2941
*/
3042
val String.filter: SearchFilter
31-
get() {
32-
val regex = Regex("\\s*\\[\\s*(\\w+)\\s*=\\s*([^\\]]+)\\s*\\]\\s*")
33-
val map = hashMapOf<String, String>()
34-
regex.findAll(this).forEach { map.put(it.groups[1]!!.value, it.groups[2]!!.value) }
35-
return SearchFilter(map, regex.replace(this, ""))
36-
}
43+
get() = SearchFilter.makeFilter(this)
44+
45+
///**
46+
// * Creates a [SearchFilter] from the filter text.
47+
// */
48+
//fun String.makeFilter() = SearchFilter.makeFilter(this)

0 commit comments

Comments
 (0)