//
// Copyright (c) 2009, Brian Frank and Andy Frank
// Licensed under the Academic Free License version 3.0
//
// History:
// 10 Jan 09 Brian Frank Creation
//
using xml
**
** ObixUtil encapsulates utility functions.
**
internal class ObixUtil
{
//////////////////////////////////////////////////////////////////////////
// Element Names
//////////////////////////////////////////////////////////////////////////
**
** Map val types to element names
**
internal static const Str:Bool elemNames :=
[
"obj": true,
"bool": true,
"int": true,
"real": true,
"str": true,
"enum": true,
"uri": true,
"abstime": true,
"reltime": true,
"date": true,
"time": true,
"list": true,
"op": true,
"feed": true,
"ref": true,
"err": true,
] { def = false }
//////////////////////////////////////////////////////////////////////////
// Value -> Element
//////////////////////////////////////////////////////////////////////////
**
** Map val types to element names
**
internal static const Type:Str valTypeToElemName :=
[
Bool#: "bool",
Int#: "int",
Float#: "real",
Str#: "str",
Uri#: "uri",
DateTime#: "abstime",
Duration#: "reltime",
Date#: "date",
Time#: "time",
]
//////////////////////////////////////////////////////////////////////////
// Element -> Value
//////////////////////////////////////////////////////////////////////////
**
** Map val types to element names
**
internal static const Str:Type elemNameToValType
static
{
map := Str:Type[:]
valTypeToElemName.each |v, k| { map[v] = k }
map["enum"] = Str#
elemNameToValType = map
}
//////////////////////////////////////////////////////////////////////////
// Value -> Str
//////////////////////////////////////////////////////////////////////////
** Encode the value in its XML string encoding (not necessarily escaped)
internal static Str valToStr(Obj? val)
{
if (val == null) return "null"
func := valTypeToStrFunc[Type.of(val)]
if (func != null) return func(val)
return val.toStr
}
** Map of value types to string format
** funcs (only those that don't use toStr)
internal static const Type:|Obj->Str| valTypeToStrFunc :=
[
Uri#: |Uri v->Str| { return v.encode },
DateTime#: |DateTime v->Str| { return v.toIso },
Duration#: |Duration v->Str| { return v.toIso },
Date#: |Date v->Str| { return v.toIso },
Time#: |Time v->Str| { return v.toIso },
]
//////////////////////////////////////////////////////////////////////////
// Str -> Value
//////////////////////////////////////////////////////////////////////////
** Map of element names to functions to parse a string
internal const static Str:|Str,XElem->Obj| elemNameToFromStrFunc :=
[
"bool": |Str s->Obj| { return Bool.fromStr(s, true) },
"int": |Str s->Obj| { return Int.fromStr(s, 10, true) },
"real": |Str s->Obj| { return Float.fromStr(s, true) },
"str": |Str s->Obj| { return s },
"uri": |Str s->Obj| { return parseUri(s) },
"enum": |Str s->Obj| { return s },
"abstime": |Str s, XElem elem->Obj| { return parseAbstime(s, elem) },
"reltime": |Str s->Obj| { return Duration.fromIso(s, true) },
"date": |Str s->Obj| { return Date.fromIso(s, true) },
"time": |Str s->Obj| { return Time.fromIso(s, true) }
]
** Map of element names to functions to parse a min/max string
internal const static Str:|Str,XElem->Obj| elemNameToMinMaxFunc :=
[
"int": |Str s->Obj| { return Int.fromStr(s, 10, true) },
"real": |Str s->Obj| { return Float.fromStr(s, true) },
"str": |Str s->Obj| { return Int.fromStr(s, 10, true) },
"abstime": |Str s, XElem elem->Obj| { return parseAbstime(s, elem) },
"reltime": |Str s->Obj| { return Duration.fromIso(s, true) },
"date": |Str s->Obj| { return Date.fromIso(s, true) },
"time": |Str s->Obj| { return Time.fromIso(s, true) }
]
internal static Uri parseUri(Str s)
{
try { return Uri.decode(s) } catch (Err e) {}
return Uri(s)
}
internal static DateTime parseAbstime(Str s, XElem elem)
{
try
{
// if year is out of Fantom range, then just set to 1901/2099
year := s[0..3].toInt
if (year < 1901) s = "1901" + s[4..-1]
else if (year > 2099) s = "2099" + s[4..-1]
}
catch {}
tz := elem.get("tz", false)
if (tz == null) return DateTime.fromIso(s, true)
swizzle := tzSwizzles[tz]
if (swizzle != null) tz = swizzle.name
return DateTime.fromStr("$s $tz", true)
}
internal static const Str:TimeZone tzSwizzles :=
[
"EST": TimeZone("New_York"), "EDT": TimeZone("New_York"),
"CST": TimeZone("Chicago"), "CDT": TimeZone("Chicago"),
"MST": TimeZone("Denver"), "MDT": TimeZone("Denver"),
"PST": TimeZone("Los_Angeles"), "PDT": TimeZone("Los_Angeles"),
]
//////////////////////////////////////////////////////////////////////////
// Element -> Default Value
//////////////////////////////////////////////////////////////////////////
** Map of element names to default values
internal const static Str defaultsToNull := "__null!__"
internal const static Str:Obj elemNameToDefaultVal :=
[
"bool": false,
"int": 0,
"real": 0f,
"str": "",
"uri": ``,
"reltime": 0sec,
"enum": defaultsToNull,
"abstime": defaultsToNull,
"date": defaultsToNull,
"time": defaultsToNull,
]
}