diff --git a/jdr/type.go b/jdr/type.go index 58ddf80..b4de5a3 100644 --- a/jdr/type.go +++ b/jdr/type.go @@ -8,16 +8,17 @@ import( "strings" "strconv" "regexp" - "encoding/json" ) var regexp_d = regexp.MustCompile(`^[1-9][0-9]*d([468]|1[02]|20|100)$`) +type JsonValue interface{} + type VariableType interface { Name() string - Validate(value string) bool - ToHTML(value string) (template.HTML, error) - DefaultValue() string + Validate(value JsonValue) bool + ToHTML(value JsonValue) (template.HTML, error) + DefaultValue() JsonValue } type VariableType_badType struct {} @@ -26,15 +27,15 @@ func (*VariableType_badType) Name() string { return "unknown type" } -func (*VariableType_badType) Validate(s string) bool { +func (*VariableType_badType) Validate(s JsonValue) bool { return false } -func (*VariableType_badType) ToHTML(value string) (template.HTML, error) { +func (*VariableType_badType) ToHTML(value JsonValue) (template.HTML, error) { return template.HTML(""), errors.New("unknown type") } -func (*VariableType_badType) DefaultValue() string { +func (*VariableType_badType) DefaultValue() JsonValue { return "" } @@ -44,23 +45,21 @@ func (*VariableType_bool) Name() string { return "bool" } -func (*VariableType_bool) ToBool(value string) (bool, error) { - switch strings.ToLower(value) { - case "true": - return true, nil - case "false": - return false, nil - default: - return false, errors.New("unknown bool value") +func (*VariableType_bool) ToBool(value JsonValue) (bool, error) { + val, isBool := value.(bool) + if !isBool { + return false, errors.New("Non boolean value") } + + return val, nil } -func (self *VariableType_bool) Validate(value string) bool { +func (self *VariableType_bool) Validate(value JsonValue) bool { _, err := self.ToBool(value) return err == nil } -func (self *VariableType_bool) ToHTML(value string) (template.HTML, error) { +func (self *VariableType_bool) ToHTML(value JsonValue) (template.HTML, error) { val, err := self.ToBool(value) if err != nil { return template.HTML(""), err @@ -75,8 +74,8 @@ func (self *VariableType_bool) ToHTML(value string) (template.HTML, error) { return template.HTML(ret), nil } -func (self *VariableType_bool) DefaultValue() string { - return "false" +func (self *VariableType_bool) DefaultValue() JsonValue { + return false } type VariableType_int struct {} @@ -85,16 +84,26 @@ func (*VariableType_int) Name() string { return "int" } -func (self *VariableType_int) ToInt(value string) (int64, error) { - return strconv.ParseInt(value, 10, 64) +func (self *VariableType_int) ToInt(value JsonValue) (int64, error) { + val, isInt := value.(int64) + if !isInt { + val2, isInt := value.(int) + if isInt { + val = int64(val2) + } else { + return 0, errors.New("Not int")) + } + } + + return val, nil } -func (self *VariableType_int) Validate(value string) bool { +func (self *VariableType_int) Validate(value JsonValue) bool { _, err := self.ToInt(value) return err == nil } -func (self *VariableType_int) ToHTML(value string) (template.HTML, error) { +func (self *VariableType_int) ToHTML(value JsonValue) (template.HTML, error) { val, err := self.ToInt(value) if err != nil { return template.HTML(""), err @@ -104,8 +113,8 @@ func (self *VariableType_int) ToHTML(value string) (template.HTML, error) { return template.HTML(ret), nil } -func (self *VariableType_int) DefaultValue() string { - return "0" +func (self *VariableType_int) DefaultValue() JsonValue { + return 0 } type VariableType_float struct {} @@ -114,16 +123,21 @@ func (*VariableType_float) Name() string { return "float" } -func (*VariableType_float) ToFloat(value string) (float64, error) { - return strconv.ParseFloat(value, 64) +func (*VariableType_float) ToFloat(value JsonValue) (float64, error) { + val, isFloat := value.(float64) + if !isFloat { + return 0.0, errors.New("Not a float") + } + + return val, nil } -func (self *VariableType_float) Validate(value string) bool { +func (self *VariableType_float) Validate(value JsonValue) bool { _, err := self.ToFloat(value) return err == nil } -func (self *VariableType_float) ToHTML(value string) (template.HTML, error) { +func (self *VariableType_float) ToHTML(value JsonValue) (template.HTML, error) { val, err := self.ToFloat(value) if err != nil { return template.HTML(""), err @@ -134,8 +148,8 @@ func (self *VariableType_float) ToHTML(value string) (template.HTML, error) { return template.HTML(ret), nil } -func (self *VariableType_float) DefaultValue() string { - return "0.0" +func (self *VariableType_float) DefaultValue() JsonValue { + return 0.0 } type VariableType_string struct {} @@ -144,16 +158,31 @@ func (*VariableType_string) Name() string { return "string" } -func (*VariableType_string) Validate(s string) bool { - return true +func (self *VariableType_string) ToString(value JsonValue) (string, error) { + val, isString := value.(string) + if !isString { + return "", errors.New("Not a string") + } + + return val, nil } -func (self *VariableType_string) ToHTML(value string) (template.HTML, error) { - ret := `` +func (self *VariableType_string) Validate(value JsonValue) bool { + _, err := self.ToString(value) + return err != nil +} + +func (self *VariableType_string) ToHTML(value JsonValue) (template.HTML, error) { + str, err := self.ToString(value) + if err != nil { + return template.HTML(""), err + } + + ret := `` return template.HTML(ret), nil } -func (self *VariableType_string) DefaultValue() string { +func (self *VariableType_string) DefaultValue() JsonValue { return "" } @@ -163,18 +192,19 @@ func (*VariableType_d) Name() string { return "d" } -func (*VariableType_d) Validate(s string) bool { - return regexp_d.MatchString(s) +func (*VariableType_d) Validate(value JsonValue) bool { + //FIXME + return false } -func (self *VariableType_d) ToHTML(value string) (template.HTML, error) { +func (self *VariableType_d) ToHTML(value JsonValue) (template.HTML, error) { //FIXME: non-generic version - ret := `` + ret := `` return template.HTML(ret), nil } -func (self *VariableType_d) DefaultValue() string { +func (self *VariableType_d) DefaultValue() JsonValue { //FIXME: non-generic version return "" } @@ -199,7 +229,6 @@ func makeVariableType(s string) VariableType { type CustomEnum struct { name string - BaseType VariableType Values []string } @@ -207,13 +236,14 @@ func (self *CustomEnum) Name() string { return self.name } -func (self *CustomEnum) ToId(value string) (int, error) { - if !self.BaseType.Validate(value) { - return 0, errors.New("Invalid value") +func (self *CustomEnum) ToId(value JsonValue) (int, error) { + val, isString := value.(string) + if !isString { + return 0, errors.New("Enum value not a string") } for i := 0; i < len(self.Values); i++ { - if self.Values[i] == value { + if self.Values[i] == val { return i, nil } } @@ -221,13 +251,17 @@ func (self *CustomEnum) ToId(value string) (int, error) { return 0, errors.New("No such element") } -func (self *CustomEnum) Validate(value string) bool { +func (self *CustomEnum) Validate(value JsonValue) bool { _, err := self.ToId(value) return err == nil } -func (self *CustomEnum) ToHTML(value string) (template.HTML, error) { - selectItem := value != "" +func (self *CustomEnum) ToHTML(value JsonValue) (template.HTML, error) { + val, isString := value.(string) + if !isString { + return template.HTML(""), errors.New("Bad enum value") + } + selectItem := val != "" value_id := 0 if selectItem { @@ -253,10 +287,12 @@ func (self *CustomEnum) ToHTML(value string) (template.HTML, error) { return template.HTML(ret), nil } -func (self *CustomEnum) DefaultValue() string { +func (self *CustomEnum) DefaultValue() JsonValue { return "" } +type JsonObject map[string]interface{} + type CustomStruct struct { name string Variables []*Variable @@ -266,17 +302,16 @@ func (self *CustomStruct) Name() string { return self.name } -func (self *CustomStruct) Validate(s string) bool { - var jsonValue map[string]interface{} - err := json.Unmarshal([]byte(s), &jsonValue) - if err != nil { - log.Fatal(err) +func (self *CustomStruct) Validate(value JsonValue) bool { + obj, isObj := value.(JsonObject) + if !isObj { + log.Println("Struct \"" + self.Name() + "\": value is not a JSON object") return false } for _, v := range self.Variables { - jsonVal, isString := jsonValue[v.Name()].(string) - if !isString || ! v.Type.Validate(jsonVal) { + if !v.Type.Validate(obj[v.Name()]) { + log.Println("Struct \"" + self.Name() + "\": value \"" + v.Name() + "\" was not validated") return false } } @@ -284,25 +319,19 @@ func (self *CustomStruct) Validate(s string) bool { return true } -func (self *CustomStruct) ToHTML(value string) (template.HTML, error) { - - var jsonValue map[string]interface{} - err := json.Unmarshal([]byte(value), &jsonValue) - if err != nil { - log.Fatal(err) - return template.HTML(""), errors.New("Cannot unmarshal JSON") +func (self *CustomStruct) ToHTML(value JsonValue) (template.HTML, error) { + if !self.Validate(value) { + return template.HTML(""), errors.New("Cannot validate struct") } + obj, _ := value.(JsonObject) + ret := template.HTML("") ret += `