masterServicemdl.go 6.54 KiB
Newer Older
Roshan Patil's avatar
Roshan Patil committed
package routebuildermdl

import (
	"encoding/json"
	"strconv"
	"strings"
	"time"
Roshan Patil's avatar
Roshan Patil committed

	"corelab.mkcl.org/MKCLOS/coredevelopmentplatform/corepkgv2/servicebuildermdl"

Roshan Patil's avatar
Roshan Patil committed
	"corelab.mkcl.org/MKCLOS/coredevelopmentplatform/corepkgv2/dalmdl/dao"

	"corelab.mkcl.org/MKCLOS/coredevelopmentplatform/corepkgv2/loggermdl"

	"corelab.mkcl.org/MKCLOS/coredevelopmentplatform/corepkgv2/errormdl"

	"corelab.mkcl.org/MKCLOS/coredevelopmentplatform/corepkgv2/dalmdl/mongodb"

	"github.com/tidwall/gjson"
)

// Master - struct for master Service
type Master struct {
	serviceName  string
	isCach       bool
	cacheTime    time.Duration
	isRestricted bool
	isRoleBased  bool
	isMongo      bool
Roshan Patil's avatar
Roshan Patil committed
}

// MongoQuery - for mongo service
type MongoQuery struct {
	collection         string
	host               string
	query              string
	projectionQuery    string
	args               []string
	isAggregationQuery bool
Roshan Patil's avatar
Roshan Patil committed
}

// FDBQuery - for fdb services
type FDBQuery struct {
	filePath string
	query    []string
Roshan Patil's avatar
Roshan Patil committed
}

// Runable - helps to run
type Runable struct {
	Master
	MongoQuery
	FDBQuery
}

// MongoService - return mongo query object
func (m *Master) MongoService(collectionName, mongoQuery string) *Runable {
	mongo := MongoQuery{
		collection: collectionName,
		query:      mongoQuery,
	m.isMongo = true
	runable := &Runable{
		Master:     *m,
		MongoQuery: mongo,
	}
	return runable
}

// MongoServiceWithHost - return mongo query object
func (m *Master) MongoServiceWithHost(hostName, collectionName, mongoQuery string) *Runable {
Roshan Patil's avatar
Roshan Patil committed
	mongo := MongoQuery{
		host:       hostName,
		collection: collectionName,
		query:      mongoQuery,
Roshan Patil's avatar
Roshan Patil committed
	}
	m.isMongo = true
Roshan Patil's avatar
Roshan Patil committed
	runable := &Runable{
		Master:     *m,
		MongoQuery: mongo,
	}
	return runable
}

// FDBService - return mongo query object
func (m *Master) FDBService(filPath string, query ...string) *Runable {
	FDB := FDBQuery{
		filePath: filPath,
		query:    query,
Roshan Patil's avatar
Roshan Patil committed
	}
	runable := &Runable{
		Master:   *m,
		FDBQuery: FDB,
	}
	return runable
}

// IsCachable for both fdb and mongo
func (m *Master) IsCachable() *Master {
	return m
}

// IsCachableWithExpiration for both fdb and mongo
func (m *Master) IsCachableWithExpiration(cacheExpirationTime time.Duration) *Master {
	m.isCach = true
	m.cacheTime = cacheExpirationTime
Roshan Patil's avatar
Roshan Patil committed
	return m
}

// SetArgs set argument for query string
func (m *Runable) SetArgs(args ...string) *Runable {
	if m.Master.isMongo {
		m.MongoQuery.args = args
	}
	return m
}

// SetProjectionQuery set SetProjectionQuery for query string
func (m *Runable) SetProjectionQuery(query string) *Runable {
	if m.Master.isMongo {
		m.MongoQuery.projectionQuery = query
	}
	return m
}

// IsAggregationQuery - Set flag for aggregation query
func (m *Runable) IsAggregationQuery() *Runable {
	if m.Master.isMongo {
		m.MongoQuery.isAggregationQuery = true
Roshan Patil's avatar
Roshan Patil committed
	}
	return m
}

// Register - register it in cacahe
func (m *Runable) Register() {
	service := ServiceCache{
		MasterService:   m,
		IsMasterService: true,
	}
	commonServiceRegistration(m.Master.serviceName, service, m.Master.isRestricted, m.Master.isRoleBased)
Roshan Patil's avatar
Roshan Patil committed
}

// Run - execute and return output and error
func (m *Runable) Run(data []byte, principal *servicebuildermdl.Principal) (interface{}, error) {
	if m.Master.isMongo {
		return m.runMongoService(data, principal)
Roshan Patil's avatar
Roshan Patil committed
	}
	return m.runFDBService()
}

func (m *Runable) runMongoService(data []byte, principal *servicebuildermdl.Principal) (interface{}, error) {
Roshan Patil's avatar
Roshan Patil committed
	rs := gjson.ParseBytes(data)
	tmp := m.MongoQuery.query
	var principalError error
	tmp, principalError = parsePricipalObject(tmp, principal)
	if errormdl.CheckErr(principalError) != nil {
		loggermdl.LogError(principalError)
		return nil, errormdl.CheckErr(principalError)
	}
	if m.MongoQuery.isAggregationQuery {
		v, formatError := m.formatAggregateQuery(&rs, tmp)
		if errormdl.CheckErr(formatError) != nil {
			loggermdl.LogError(formatError)
			return nil, errormdl.CheckErr(formatError)
		}
		query, getError := mongodb.GetMongoDAOWithHost(m.MongoQuery.host, m.MongoQuery.collection).GetAggregateData(v)
		if errormdl.CheckErr(getError) != nil {
			loggermdl.LogError(getError)
			return nil, errormdl.CheckErr(getError)
		}
		return query.Value(), nil
	v, p, formatError := m.formatNormalQuery(&rs, tmp)
	if errormdl.CheckErr(formatError) != nil {
		loggermdl.LogError(formatError)
		return nil, errormdl.CheckErr(formatError)
Roshan Patil's avatar
Roshan Patil committed
	}
	query, getError := mongodb.GetMongoDAOWithHost(m.MongoQuery.host, m.MongoQuery.collection).GetProjectedData(v, p)
Roshan Patil's avatar
Roshan Patil committed
	if errormdl.CheckErr(getError) != nil {
		loggermdl.LogError(getError)
		return nil, errormdl.CheckErr(getError)
	}
Roshan Patil's avatar
Roshan Patil committed
	return query.Value(), nil
func (m *Runable) formatAggregateQuery(rs *gjson.Result, tmp string) ([]interface{}, error) {
	for i, arg := range m.MongoQuery.args {
		result := rs.Get(arg).String()
		argNotation := "~" + strconv.Itoa(i+1)
		tmp = strings.Replace(tmp, argNotation, result, 1)
	}
	v, ok := gjson.Parse(tmp).Value().([]interface{})
	if !ok {
		loggermdl.LogError("Invalid Mongo Query")
		return nil, errormdl.Wrap("Invalid Mongo Query")
	}
	return v, nil
}

func (m *Runable) formatNormalQuery(rs *gjson.Result, tmp string) (map[string]interface{}, map[string]interface{}, error) {
	for i, arg := range m.MongoQuery.args {
		result := rs.Get(arg).String()
		argNotation := "~" + strconv.Itoa(i+1)
		tmp = strings.Replace(tmp, argNotation, result, 1)
	}

	v, ok := gjson.Parse(tmp).Value().(map[string]interface{})
	if !ok {
		loggermdl.LogError("Invalid Mongo Query")
		return nil, nil, errormdl.Wrap("Invalid Mongo Query")
	}
	if m.MongoQuery.projectionQuery == "" {
		m.MongoQuery.projectionQuery = "{}"
	}
	p, ok := gjson.Parse(m.MongoQuery.projectionQuery).Value().(map[string]interface{})
	if !ok {
		loggermdl.LogError("Invalid Mongo Projection Query Query")
		return nil, nil, errormdl.Wrap("Invalid Mongo Projection Query Query")
	}
	return v, p, nil
}

func parsePricipalObject(query string, principal *servicebuildermdl.Principal) (string, error) {
	ba, marshalError := json.Marshal(principal)
	if errormdl.CheckErr(marshalError) != nil {
		loggermdl.LogError(marshalError)
		return "", errormdl.CheckErr(marshalError)
	}
	pricipalRS := gjson.ParseBytes(ba)
	result := pricipalRS.Get("userId").String()
	argNotation := "~tokenUserId"
	query = strings.Replace(query, argNotation, result, 1)
	return query, nil
}

Roshan Patil's avatar
Roshan Patil committed
func (m *Runable) runFDBService() (interface{}, error) {
	rs, getError := dalmdl.GetDAO().
		FilePath(m.FDBQuery.filePath).
		Query(m.FDBQuery.query...).
		IsCacheableWithDuration(m.Master.cacheTime).
Roshan Patil's avatar
Roshan Patil committed
		Run()
	if errormdl.CheckErr(getError) != nil {
		loggermdl.LogError(getError)
		return nil, errormdl.CheckErr(getError)
	}
	return rs.Value(), nil
}