blob: 2a7827764d69914ee41051b275e57ef5cd33d597 [file] [log] [blame]
// message.go
package swservice
import (
"encoding/json"
"errors"
"fmt"
// "reflect"
"strconv"
)
type MessageWriter struct {
FuncNo int `json: "funcno"`
Attributes map[string]interface{}
ColumnNames []string
ColumnDescs []string
RowData []map[string]interface{}
Row map[string]interface{}
}
func NewMessageWriter(funcno int) *MessageWriter {
return &MessageWriter{
FuncNo: funcno,
Attributes: make(map[string]interface{}),
ColumnNames: make([]string, 0),
ColumnDescs: make([]string, 0),
RowData: make([]map[string]interface{}, 0)}
}
func (m *MessageWriter) SetAttr(name string, value interface{}) {
m.Attributes[name] = value
}
func (m *MessageWriter) AddCol(name string, value interface{}) {
if m.Row == nil {
m.Row = make(map[string]interface{})
}
m.Row[name] = value
}
func is_contains(k string, slice []string) bool {
for _, v := range slice {
if k == v {
return true
}
}
return false
}
func (m *MessageWriter) AddRow() {
if m.Row == nil {
return
}
// data := make([]interface{}, 0)
// if len(m.ColumnNames) == 0 {
// for k, v := range m.Row {
// m.ColumnNames = append(m.ColumnNames, k)
// data = append(data, v)
// }
// } else {
// for _, n := range m.ColumnNames {
// if v, ok := m.Row[n]; !ok {
// data = append(data, nil)
// } else {
// data = append(data, v)
// }
// }
// for k, v := range m.Row {
// if !is_contains(k, m.ColumnNames) {
// m.ColumnNames = append(m.ColumnNames, k)
// data = append(data, v)
// }
// }
// }
// m.RowData = append(m.RowData, data)
m.RowData = append(m.RowData, m.Row)
m.Row = nil
}
func (m *MessageWriter) serialize_rowdata() {
m.ColumnNames = make([]string, 0)
for _, row := range m.RowData {
for k, _ := range row {
if !is_contains(k, m.ColumnNames) {
m.ColumnNames = append(m.ColumnNames, k)
}
}
}
rows := make([][]interface{}, 0)
for _, row := range m.RowData {
data := make([]interface{}, 0)
for _, k := range m.ColumnNames {
if v, ok := row[k]; !ok {
data = append(data, nil)
} else {
data = append(data, v)
}
}
rows = append(rows, data)
}
m.Attributes["rowdata"] = rows
m.Attributes["rowcnt"] = len(rows)
}
func (m *MessageWriter) Serialize() string {
m.Attributes["funcno"] = m.FuncNo
m.serialize_rowdata()
m.Attributes["colname"] = m.ColumnNames
m.Attributes["coldesc"] = m.ColumnNames
m.Attributes["colcnt"] = len(m.ColumnNames)
r, _ := json.Marshal(m.Attributes)
return string(r)
}
//////////////////////////////////////////////////////////////////////
type MessageReader struct {
FuncNo int
RetCode int
RetMsg string
DBMsg string
ErrName string
ColumnNames []string
ColumnDescs []string
Attributes map[string]interface{}
RowData []map[string]interface{}
RowIndex int
}
func get_value_as_int(value interface{}) int {
// vtype := reflect.TypeOf(value)
switch value.(type) {
case int:
return value.(int)
case float64:
return int(value.(float64))
case string:
i, _ := strconv.Atoi(value.(string))
return i
default:
panic("Error")
}
}
func get_column_names(data interface{}) (result []string) {
if data == nil {
return nil
}
names := data.([]interface{})
result = make([]string, 0)
for _, v := range names {
result = append(result, v.(string))
}
return
}
func convert_to_int(value interface{}) int {
if value == nil {
return 0
}
switch value.(type) {
case int:
return value.(int)
case float64:
return int(value.(float64))
case string:
i, _ := strconv.Atoi(value.(string))
return i
default:
return 0
}
}
func convert_to_string(value interface{}) string {
if value == nil {
return ""
}
return fmt.Sprintf("%v", value)
}
func NewMessageReader(data []byte) *MessageReader {
var s interface{}
err := json.Unmarshal(data, &s)
if err != nil {
return nil
}
obj := s.(map[string]interface{})
m := &MessageReader{Attributes: make(map[string]interface{}),
RowData: make([]map[string]interface{}, 0)}
m.FuncNo = convert_to_int(obj["funcno"])
m.RetCode = convert_to_int(obj["retcode"])
m.RetMsg = convert_to_string(obj["retmsg"])
m.DBMsg = convert_to_string(obj["dbmsg"])
m.ErrName = convert_to_string(obj["errname"])
m.ColumnNames = get_column_names(obj["colname"])
m.ColumnDescs = get_column_names(obj["coldesc"])
if rowdata, err := obj["rowdata"]; err {
if rowdata != nil {
for _, raw := range rowdata.([]interface{}) {
row := raw.([]interface{})
data := make(map[string]interface{})
for idx, v := range row {
data[m.ColumnNames[idx]] = v
}
m.RowData = append(m.RowData, data)
}
}
}
reverseKey := map[string]bool{
"funcno": true,
"colname": true,
"coldesc": true,
"rowcnt": true,
"colcnt": true,
"rowdata": true,
"retcode": true,
"retmsg": true,
"dbmsg": true,
"errname": true}
for k, v := range obj {
if _, ok := reverseKey[k]; ok {
continue
}
m.Attributes[k] = v
}
return m
}
func (m *MessageReader) RowCount() int {
return len(m.RowData)
}
func (m *MessageReader) HasMore() bool {
return m.RowIndex < m.RowCount()
}
func (m *MessageReader) NextRow() error {
m.RowIndex++
if m.RowIndex > m.RowCount() {
return errors.New("Eof of row")
}
return nil
}
func (m *MessageReader) GetCol(name string) interface{} {
idx := m.RowIndex - 1
if v, ok := m.RowData[idx][name]; !ok {
return nil
} else {
return v
}
}
func (m *MessageReader) GetColAsInt(name string) int {
v := m.GetCol(name)
switch v.(type) {
case float32:
return int(v.(float32))
case float64:
return int(v.(float64))
case int:
return v.(int)
case string:
i, _ := strconv.Atoi(v.(string))
return i
default:
return 0
}
}
func (m *MessageReader) GetColAsString(name string) string {
v := m.GetCol(name)
return fmt.Sprintf("%v", v)
}
func (m *MessageReader) GetColAsDouble(name string) float64 {
v := m.GetCol(name)
switch v.(type) {
case float32:
return float64(v.(float32))
case float64:
return v.(float64)
case int:
return float64(v.(int))
case string:
i, _ := strconv.ParseFloat(v.(string), 64)
return i
default:
return 0
}
}
func (m *MessageReader) GetAttr(name string) interface{} {
if v, ok := m.Attributes[name]; !ok {
return nil
} else {
return v
}
}