Skip to content

Commit

Permalink
Merge branch 'development'
Browse files Browse the repository at this point in the history
  • Loading branch information
martawoldanska committed Aug 8, 2018
2 parents 52b6308 + 9d41d51 commit ebb1037
Show file tree
Hide file tree
Showing 83 changed files with 1,606 additions and 414 deletions.
2 changes: 1 addition & 1 deletion CockpitCore/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ plugins {
}

group 'com.polidea.cockpit'
version '2.0.0'
version '2.1.0'

repositories {
google()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.polidea.cockpit.core


fun <T : Any> CockpitParam<T>.isSimpleParam(): Boolean = isValueSimpleType() && !hasOptionalFields()

private fun <T : Any> CockpitParam<T>.isValueSimpleType() = when (value) {
is Number -> true
is Boolean -> true
is String -> true
else -> false
}

private fun <T : Any> CockpitParam<T>.hasOptionalFields() = description != null || group != null
11 changes: 11 additions & 0 deletions CockpitCore/src/main/java/com/polidea/cockpit/core/ColorMatcher.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.polidea.cockpit.core

import java.util.regex.Pattern

object ColorMatcher {

private const val hexColorRegex = "^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{8})\$"
private val hexColorPattern = Pattern.compile(hexColorRegex)

fun isHexColor(color: String) = hexColorPattern.matcher(color).matches()
}
106 changes: 0 additions & 106 deletions CockpitCore/src/main/java/com/polidea/cockpit/core/ParamsMapper.kt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.polidea.cockpit.core

import com.polidea.cockpit.core.mapper.ParamsMapper
import org.yaml.snakeyaml.LoaderOptions
import org.yaml.snakeyaml.Yaml
import java.io.File
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.polidea.cockpit.core.mapper

internal class MapperConsts {

internal companion object {
const val KEY_TYPE = "type"
const val KEY_DESCRIPTION = "description"
const val KEY_VALUE = "value"
const val KEY_GROUP = "group"

const val KEY_ACTION_BUTTON_TEXT = "buttonText"

const val KEY_LIST_VALUES = "values"
const val KEY_LIST_SELECTION_INDEX = "selectedItemIndex"

const val KEY_RANGE_MIN = "min"
const val KEY_RANGE_MAX = "max"
const val KEY_RANGE_STEP = "step"
const val KEY_RANGE_VALUE = "value"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package com.polidea.cockpit.core.mapper

import com.polidea.cockpit.core.CockpitParam
import com.polidea.cockpit.core.isSimpleParam
import com.polidea.cockpit.core.type.CockpitAction
import com.polidea.cockpit.core.type.CockpitColor
import com.polidea.cockpit.core.type.CockpitListType
import com.polidea.cockpit.core.type.CockpitRange

internal class ParamToYamlMapper {

fun toYamlMap(params: List<CockpitParam<Any>>): Map<String, Any> {
return linkedMapOf(*params.map {
if (it.isSimpleParam())
toSimpleYamlFormat(it)
else
toExtendedYamlFormat(it)

}.toTypedArray())
}

private fun toSimpleYamlFormat(it: CockpitParam<Any>) = Pair(it.name, it.value)

private fun toExtendedYamlFormat(it: CockpitParam<Any>): Pair<String, LinkedHashMap<String, Any>> {
val map = linkedMapOf<String, Any>()
val value = it.value
when (value) {
is CockpitAction -> {
map[MapperConsts.KEY_TYPE] = YamlParamType.ACTION.value
value.buttonText?.let { map[MapperConsts.KEY_ACTION_BUTTON_TEXT] = it }
}
is CockpitListType<*> -> {
map[MapperConsts.KEY_TYPE] = YamlParamType.LIST.value
map[MapperConsts.KEY_LIST_VALUES] = value.items
map[MapperConsts.KEY_LIST_SELECTION_INDEX] = value.selectedIndex
}
is CockpitColor -> {
map[MapperConsts.KEY_TYPE] = YamlParamType.COLOR.value
map[MapperConsts.KEY_VALUE] = value.value
}
is CockpitRange<*> -> {
map[MapperConsts.KEY_TYPE] = YamlParamType.RANGE.value
map[MapperConsts.KEY_RANGE_MIN] = value.min
map[MapperConsts.KEY_RANGE_MAX] = value.max
map[MapperConsts.KEY_RANGE_STEP] = value.step
map[MapperConsts.KEY_RANGE_VALUE] = value.value
}

else -> value.let { map[MapperConsts.KEY_VALUE] = it }
}
it.description?.let { map[MapperConsts.KEY_DESCRIPTION] = it }
it.group?.let { map[MapperConsts.KEY_GROUP] = it }
return Pair(it.name, map)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.polidea.cockpit.core.mapper

import com.polidea.cockpit.core.CockpitParam

class ParamsMapper {

private val yamlMapToParamMapper = YamlToParamMapper()

private val paramToYamlMapMapper = ParamToYamlMapper()

fun toListOfParams(yamlMap: Map<String, Any>): List<CockpitParam<Any>> {
return yamlMapToParamMapper.toListOfParams(yamlMap)
}

fun toYamlMap(params: List<CockpitParam<Any>>): Map<String, Any> {
return paramToYamlMapMapper.toYamlMap(params)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.polidea.cockpit.core.mapper

internal enum class YamlParamType(val value: String) {
ACTION("action"),
LIST("list"),
COLOR("color"),
RANGE("range"),
DEFAULT("");

companion object {
fun forValue(value: String?): YamlParamType = values().find { it.value == value } ?: DEFAULT
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package com.polidea.cockpit.core.mapper

import com.polidea.cockpit.core.CockpitParam
import com.polidea.cockpit.core.exception.CockpitParseException
import com.polidea.cockpit.core.type.CockpitAction
import com.polidea.cockpit.core.type.CockpitColor
import com.polidea.cockpit.core.type.CockpitListType
import com.polidea.cockpit.core.type.CockpitRange

internal class YamlToParamMapper {

fun toListOfParams(yamlMap: Map<String, Any>): List<CockpitParam<Any>> {
return yamlMap.map {
val value = it.value
val param = when (value) {
is Map<*, *> -> fromExtendedYamlFormat(it.key, value) // new extended yaml format
else -> fromSimpleYamlFormat(it.key, value) // previous simple yaml format
}
param
}
}

private fun fromSimpleYamlFormat(paramName: String, paramValue: Any): CockpitParam<Any> {
val paramVal = when (paramValue) {
is List<*> -> CockpitListType(ArrayList<Any>(paramValue), 0)
else -> paramValue
}
return CockpitParam(paramName, paramVal)
}

private fun fromExtendedYamlFormat(paramName: String, valueMap: Map<*, *>): CockpitParam<Any> {
val type = YamlParamType.forValue(valueMap[MapperConsts.KEY_TYPE] as String?)
val value = when (type) {
YamlParamType.ACTION -> createCockpitAction(valueMap)
YamlParamType.LIST -> createCockpitListType(paramName, valueMap)
YamlParamType.COLOR -> createCockpitColor(paramName, valueMap)
YamlParamType.RANGE -> createCockpitRange(paramName, valueMap)
YamlParamType.DEFAULT -> valueMap[MapperConsts.KEY_VALUE] as Any
}
val description = valueMap[MapperConsts.KEY_DESCRIPTION] as String?
val group = valueMap[MapperConsts.KEY_GROUP] as String?
return CockpitParam(paramName, value, description, group)
}

private fun createCockpitAction(valueMap: Map<*, *>) =
CockpitAction(valueMap[MapperConsts.KEY_ACTION_BUTTON_TEXT] as? String)

private fun createCockpitListType(paramName: String, valueMap: Map<*, *>): CockpitListType<Any> {
val values = valueMap[MapperConsts.KEY_LIST_VALUES] as? List<*>
?: throw CockpitParseException("$paramName parameter must contain list of elements in `${MapperConsts.KEY_LIST_VALUES}` field")
val selectedIndex = (valueMap[MapperConsts.KEY_LIST_SELECTION_INDEX] as Int?) ?: 0
return CockpitListType(ArrayList<Any>(values), selectedIndex)
}

private fun createCockpitColor(paramName: String, valueMap: Map<*, *>): CockpitColor {
val colorValue = valueMap[MapperConsts.KEY_VALUE] as? String
?: throw CockpitParseException("$paramName must contain String value param")
try {
return CockpitColor(colorValue)
} catch (e: IllegalArgumentException) {
throw CockpitParseException("Invalid color format for `$paramName` param. Supported formats are: #RRGGBB and #AARRGGBB.")
}
}

private fun createCockpitRange(paramName: String, valueMap: Map<*, *>): CockpitRange<*> {
val min = valueMap[MapperConsts.KEY_RANGE_MIN] as? Number
?: throw CockpitParseException("$paramName parameter must contain min field")
val max = valueMap[MapperConsts.KEY_RANGE_MAX] as? Number
?: throw CockpitParseException("$paramName parameter must contain max field")
val step = valueMap[MapperConsts.KEY_RANGE_STEP] as? Number ?: 1
val selectedValue = valueMap[MapperConsts.KEY_RANGE_VALUE] as? Number ?: min

try {
if (min is Int && max is Int && step is Int && selectedValue is Int)
return CockpitRange(min.toInt(), max.toInt(), step.toInt(), selectedValue.toInt())

return CockpitRange(min.toDouble(), max.toDouble(), step.toDouble(), selectedValue.toDouble())
} catch (e: IllegalArgumentException) {
throw CockpitParseException("$paramName`s ${e.message}")
}
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
package com.polidea.cockpit.core.type

class CockpitAction(val buttonText: String?)
data class CockpitAction(val buttonText: String?)
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.polidea.cockpit.core.type

import com.polidea.cockpit.core.ColorMatcher

data class CockpitColor(val value: String) {

init {
if (!ColorMatcher.isHexColor(value)) {
throw IllegalArgumentException("Unknown color")
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.polidea.cockpit.core.type

data class CockpitRange<T : Number>(val min: T, val max: T, val step: T, val value: T) {

init {
if (min.toDouble() > max.toDouble())
throw IllegalArgumentException("Max value must be greater than min value")
if (step.toDouble() <= 0)
throw IllegalArgumentException("Step value must be positive")
if (value.toDouble() < min.toDouble() || value.toDouble() > max.toDouble())
throw IllegalArgumentException("Selected value must be in the range")
}
}
Loading

0 comments on commit ebb1037

Please sign in to comment.