blob: d045a4d0a677879a852ab3be814b520b36faefa0 [file] [log] [blame]
package wsclient
import (
"encoding/json"
"errors"
"fmt"
// "reflect"
"strconv"
)
// MessageWriter writer
type MessageWriter struct {
FuncNo int `json:"funcno"`
Attributes map[string]interface{}
ColumnNames []string
ColumnDescs []string
RowData []map[string]interface{}
Row map[string]interface{}
}
// NewMessageReader reader
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)}
}
// SetAttr set attribute
func (m *MessageWriter) SetAttr(name string, value interface{}) {
m.Attributes[name] = value
}
// AddCol add column data
func (m *MessageWriter) AddCol(name string, value interface{}) {
if m.Row == nil {
m.Row = make(map[string]interface{})
}
m.Row[name] = value
}
func isContains(k string, slice []string) bool {
for _, v := range slice {
if k == v {
return true
}
}
return false
}
// AddRow add row
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) serializeRowData() {
m.ColumnNames = make([]string, 0)
for _, row := range m.RowData {
for k, _ := range row {
if !isContains(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)
}
// Serialize εΊεˆ—εŒ–
func (m *MessageWriter) Serialize() string {
m.Attributes["funcno"] = m.FuncNo
m.serializeRowData()
m.Attributes["colname"] = m.ColumnNames
m.Attributes["coldesc"] = m.ColumnNames
m.Attributes["colcnt"] = len(m.ColumnNames)
r, _ := json.Marshal(m.Attributes)
return string(r)
}
//////////////////////////////////////////////////////////////////////
// MessageReader message reader
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 getValueAsInt(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 getColumnNames(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 convertToInt(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 convertToString(value interface{}) string {
if value == nil {
return ""
}
return fmt.Sprintf("%v", value)
}
// NewMessageReader new MessageReader
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 = convertToInt(obj["funcno"])
m.RetCode = convertToInt(obj["retcode"])
m.RetMsg = convertToString(obj["retmsg"])
m.DBMsg = convertToString(obj["dbmsg"])
m.ErrName = convertToString(obj["errname"])
m.ColumnNames = getColumnNames(obj["colname"])
m.ColumnDescs = getColumnNames(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
}
// RowCount row count
func (m *MessageReader) RowCount() int {
return len(m.RowData)
}
// HasMore has more row
func (m *MessageReader) HasMore() bool {
return m.RowIndex < m.RowCount()
}
// NextRow next row
func (m *MessageReader) NextRow() error {
m.RowIndex++
if m.RowIndex > m.RowCount() {
return errors.New("Eof of row")
}
return nil
}
// GetCol get column
func (m *MessageReader) GetCol(name string) interface{} {
idx := m.RowIndex - 1
v, ok := m.RowData[idx][name]
if !ok {
return nil
}
return v
}
// GetColAsInt get column data as int
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
}
}
// GetColAsString get column data as string
func (m *MessageReader) GetColAsString(name string) string {
v := m.GetCol(name)
return fmt.Sprintf("%v", v)
}
// GetColAsDouble get column data as double
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
}
}
// GetAttr get attribute value
func (m *MessageReader) GetAttr(name string) interface{} {
v, ok := m.Attributes[name]
if !ok {
return nil
}
return v
}