|
|
|
@ -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 := `<input type="text" value="` + template.HTMLEscapeString(value) + `"/>` |
|
|
|
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 := `<input type="text" value="` + template.HTMLEscapeString(str) + `"/>` |
|
|
|
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 := `<input type="text" value="` + template.HTMLEscapeString(value) +`"/>` |
|
|
|
ret := `<input type="text" value="` /*+ template.HTMLEscapeString(value)*/ +`"/>` |
|
|
|
|
|
|
|
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 += `<div>` |
|
|
|
for _, v := range self.Variables { |
|
|
|
log.Println("variable:", v.Name()) |
|
|
|
jsonVal, isString := jsonValue[v.Name()].(string) |
|
|
|
if !isString { |
|
|
|
return template.HTML(""), errors.New("Variable " + v.Name() + " is not a string") |
|
|
|
} |
|
|
|
|
|
|
|
html, err := v.Type.ToHTML(jsonVal) |
|
|
|
html, err := v.Type.ToHTML(obj[v.Name()]) |
|
|
|
if err != nil { |
|
|
|
return template.HTML(""), err |
|
|
|
} |
|
|
|
@ -314,19 +343,11 @@ func (self *CustomStruct) ToHTML(value string) (template.HTML, error) { |
|
|
|
return ret, nil |
|
|
|
} |
|
|
|
|
|
|
|
func (self *CustomStruct) DefaultValue() string { |
|
|
|
ret := `{` |
|
|
|
for i, v := range self.Variables { |
|
|
|
if i > 0 { |
|
|
|
ret += "," |
|
|
|
} |
|
|
|
ret += `"` |
|
|
|
ret += v.Name() |
|
|
|
ret += `":"` |
|
|
|
ret += v.Type.DefaultValue() |
|
|
|
ret += `"` |
|
|
|
func (self *CustomStruct) DefaultValue() JsonValue { |
|
|
|
ret := make(JsonObject) |
|
|
|
for _, v := range self.Variables { |
|
|
|
ret[v.Name()] = v.Type.DefaultValue() |
|
|
|
} |
|
|
|
ret += `}` |
|
|
|
return ret |
|
|
|
} |
|
|
|
|
|
|
|
@ -334,7 +355,6 @@ func parseCustomEnum(root xmlNode) (*CustomEnum, error) { |
|
|
|
customEnum := CustomEnum {} |
|
|
|
|
|
|
|
nameOk := false; |
|
|
|
typeOk := false; |
|
|
|
for i := 0; i < len(root.Attrs); i++ { |
|
|
|
attrName := root.Attrs[i].Name.Local |
|
|
|
attrVal := root.Attrs[i].Value |
|
|
|
@ -343,35 +363,19 @@ func parseCustomEnum(root xmlNode) (*CustomEnum, error) { |
|
|
|
case "name": |
|
|
|
nameOk = true |
|
|
|
customEnum.name = attrVal |
|
|
|
case "base-type": |
|
|
|
typeOk = true |
|
|
|
customEnum.BaseType = makeVariableType(attrVal) |
|
|
|
switch customEnum.BaseType.(type) { |
|
|
|
case *VariableType_badType: |
|
|
|
typeOk = false |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if !nameOk { |
|
|
|
return nil, errors.New("Unnamed custom enum") |
|
|
|
} |
|
|
|
if !typeOk { |
|
|
|
return nil, errors.New("Bad base type for " + customEnum.Name()) |
|
|
|
} |
|
|
|
|
|
|
|
for i := 0; i < len(root.Nodes); i++ { |
|
|
|
node := root.Nodes[i] |
|
|
|
|
|
|
|
switch node.XMLName.Local { |
|
|
|
case "value": |
|
|
|
value := string(node.Content) |
|
|
|
if customEnum.BaseType.Validate(value) { |
|
|
|
customEnum.Values = append(customEnum.Values, value) |
|
|
|
} else { |
|
|
|
log.Println("Cannot validate value enum \"" + value + "\" with type \"" + |
|
|
|
customEnum.BaseType.Name() + "\". Discarded") |
|
|
|
} |
|
|
|
customEnum.Values = append(customEnum.Values, string(node.Content)) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|