json_utility.go 3.95 KB
package restutility

import (
	"net/http"
	"encoding/json"
	"errors"
	"gopkg.in/rana/ora.v3"
	"io"
	"io/ioutil"
	"sync"
)

var mu = &sync.Mutex{}
var allPayloads []payloadBuff

type LangMap map[string]map[string]string

type Field struct {
	Parameter  string `json:"param"`
	Type       string `json:"type"`
	Visible    bool   `json:"visible"`
	Editable   bool   `json:"editable"`
}

type CorrelationField struct {
	Result   string   `json:"result"`
	Elements []string `json:"elements"`
	Type     string   `json:"type"`
}

type Translation struct {
	Language     string            `json:"language"`
	FieldsLabels map[string]string `json:"fieldsLabels"`
}

// Field 'Type' is not required in payload.
// 'payloadBuff' type is only a bridge between ORACLE CLOB and 'Payload' type.
type payloadBuff struct {
	Type         string             `json:"tableType"`
	Method	     string             `json:"method"`
	Params	     map[string]string  `json:"params"`
	Lang	     []Translation      `json:"lang"`
	Fields	     []Field            `json:"fields"`
	Correlations []CorrelationField `json:"correlationFields"`
	IdField      string             `json:"idField"`
	// Data can only hold slices of any type. It can't be used for itteration
	Data	     interface{}        `json:"data"`
}

type Payload struct {
	Method	     string             `json:"method"`
	Params	     map[string]string  `json:"params"`
	Lang	     []Translation      `json:"lang"`
	Fields	     []Field            `json:"fields"`
	Correlations []CorrelationField `json:"correlationFields"`
	IdField      string             `json:"idField"`
	// Data can only hold slices of any type. It can't be used for itteration
	Data	     interface{}        `json:"data"`
}

func NewPayload(r *http.Request, table string) Payload {
	var pload Payload

	pload.Method = r.Method + " " + r.URL.Path

	if table != "" {
		pload.Params = make(map[string]string, 0)
		pload.Lang = loadTranslations(table)
		pload.Fields = loadFields(table)
		pload.IdField = loadIdField(table)
		pload.Correlations = loadCorrelations(table)
	}

	return pload
}

func DeliverPayload(w http.ResponseWriter, payload Payload) {
	json.NewEncoder(w).Encode(payload)
	payload.Data = nil
}

func loadTranslations(id string) []Translation {
	translations := make([]Translation, 0)

	for _, pload := range allPayloads {
		if pload.Type == id {
			for _, t := range pload.Lang {
				//translations[t.Language] = t.FieldsLabels
				translations = append(translations, Translation{
					Language: t.Language,
					FieldsLabels: t.FieldsLabels,
				})
			}
		}
	}

	return translations
}

func loadFields(id string) []Field {
	fields := make([]Field, 0)

	for _, pload := range allPayloads {
		if pload.Type == id{
			for _, f := range pload.Fields {
				fields = append(fields, f)
			}
		}
	}

	return fields
}

func loadIdField(id string) string {
	for _, pload := range allPayloads {
		if pload.Type == id {
			return pload.IdField
		}
	}
	return ""
}

func loadCorrelations(id string) []CorrelationField {
	resp := make([]CorrelationField, 0)

	for _, pload := range allPayloads {
		if pload.Type == id {
			for _, f := range pload.Correlations {
				resp = append(resp, f)
			}
		}
	}

	return resp
}

func InitTables(db *ora.Ses, project string) error {
	jsonbuf, _ := fetchJSON(db, EqualQuotes(project))
	mu.Lock()
	defer mu.Unlock()
	json.Unmarshal(jsonbuf, &allPayloads)
	if len(allPayloads) == 0 {
		return errors.New("tables config is corrupt")
	}
	return nil
}

func fetchJSON(db *ora.Ses, project string) ([]byte, error) {
	stmt, err := db.Prep(`SELECT
		JSON_CLOB
		FROM TABLES_CONFIG
		WHERE PROJEKAT` + project, ora.S)
	defer stmt.Close()

	if err != nil {
		return nil, err
	}

	rset, err := stmt.Qry()
	if err != nil {
		return nil, err
	}

	bytes := make([]byte, 0)
	if rset.Next() {
		lob := rset.Row[0].(io.Reader)
		bytes, err = ioutil.ReadAll(lob)
		if err != nil {
			// Ignore for now, it's some weird streaming read/write LOB error.
			// TODO: Find a fix for this.
			//return nil, err
		}
	}

	return bytes, nil
}