| 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 |
| } |