Skip to content
This repository has been archived by the owner on May 1, 2023. It is now read-only.

Commit

Permalink
breaking changes version 1
Browse files Browse the repository at this point in the history
- clean code
- BeforeParse now AddParse
- changing Adapter now Parse
- Changing all language
- Remove Operator, use OperatorManager + func (more easier)
- Removing Kendo prefix in all struct name
- scoping operator manager (removing scoping by operator)
  • Loading branch information
Radityo committed Mar 18, 2020
1 parent fb3268c commit 974d0c3
Show file tree
Hide file tree
Showing 38 changed files with 1,790 additions and 1,977 deletions.
2 changes: 2 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions .idea/gokendoparser.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

220 changes: 146 additions & 74 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,47 +1,70 @@
![GitHub tag (latest SemVer)](https://img.shields.io/github/tag/raditzlawliet/gokendoparser.svg?label=release)
![Codecov](https://img.shields.io/codecov/c/github/raditzlawliet/gokendoparser.svg)
[![](https://godoc.org/github.com/raditzlawliet/gokendoparser?status.svg)](http://godoc.org/github.com/raditzlawliet/gokendoparser)
[![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/raditzlawliet/gokendoparser/issues)
<!-- [![Go Report Card](https://goreportcard.com/badge/github.com/raditzlawliet/gokendoparser)](https://goreportcard.com/report/github.com/raditzlawliet/gokendoparser) -->

# Go Kendo Parser
Your Golang Kendo parser, parsing Kendo data source request to golang struct immediately. Available parser to
![GitHub tag (latest SemVer)](https://img.shields.io/github/tag/raditzlawliet/kendoparser.svg?label=release)
![Codecov](https://img.shields.io/codecov/c/github/raditzlawliet/kendoparser.svg)
[![](https://godoc.org/github.com/raditzlawliet/kendoparser?status.svg)](http://godoc.org/github.com/raditzlawliet/kendoparser)
[![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/raditzlawliet/kendoparser/issues)
<!-- [![Go Report Card](https://goreportcard.com/badge/github.com/raditzlawliet/kendoparser)](https://goreportcard.com/report/github.com/raditzlawliet/kendoparser) -->

# Golang Kendo Parser (v 1.*)
Parsing Kendo DataSource filter & sort request to any kind of data in go that can immediately serve to mongo query or aggregate and other ORMs. Already used in EACIIT's environment and can be scale-able for generic purpose. Currently there are few parser available:
- [mongo-go-driver Filter](https://github.com/mongodb/mongo-go-driver/) (mainly used for primary test)
- [eaciit/dbox Filter](https://github.com/eaciit/dbox)
- [eaciit/dbox Pipe or Aggregation type](https://github.com/eaciit/dbox)
- sebar/dbflex Filter
- [mongo-go-driver Filter](https://github.com/mongodb/mongo-go-driver/)
- [xorm/builder Filter](https://gitea.com/xorm/builder/) This builder have nice ToSQL function, so you can transform into SQL

## Features
- Convert kendo datasource request into go struct
- Basic Operator
- Transform filter + Chaining
- Plugable operator handler
- Parser Sort
- Custom pre-filter / before parse handler
- Extendable to any result
- Parse Kendo DataSource request into go struct
- Parse Kendo DataSource request into filter & sort database / orm-ish
- Transforming filter + Chaining
- Customizable filter operator
- Additional Pre-parse filter
- Adaptor based, customizable parse into other generic purpose
- Kendo Request Wrapper
- Go mod support

## Getting Started
Go get, import, use
- Install
```sh
go get -v raditzlawliet/kendoparser
```

- Import
```go
import (
kp "github.com/raditzlawliet/kendoparser"
kpmongo "github.com/raditzlawliet/kendoparser/parser/kpmongo"
)
```
- Use
```go
request := struct {
Filter kp.Filter,
Sort kp.Sort,
}{}

### Parse Filter
#### JSON Sample
filter := request.Filter.Parse(kpmongo.FilterParser)
sort := request.Sort.Parse(kpmongo.SortParser)
```
#### How to use Parse Filter
- JSON Sample
```json
{
"data": {
"filter": {
"field": "id",
"operator": "eq",
"value": "val",
"value": "val"
}
}
}
```

#### GO Implementation
- GO Implementation
```go
import kpmgo "github.com/raditzlawliet/gokendoparser/adapter/mgo"
import kpmongo "github.com/raditzlawliet/kendoparser/parser/kpmongo"
```

```go
// just for information
// you can use gorilla mux or knot
var k = k *knot.WebContext
Expand All @@ -59,11 +82,11 @@ payload := KendoRequest {
},
}

filter := payload.Data.Filter.Parse(kpmongo.ParseFilter)
sort := payload.Data.Sort.Parse(kpmongo.ParseSort)
filter := payload.Data.Filter.Parse(kpmongo.FilterParser)
sort := payload.Data.Sort.Parse(kpmongo.SortParser)
```

#### More JSON
- More Example
```json
{
"data": {
Expand All @@ -72,14 +95,14 @@ sort := payload.Data.Sort.Parse(kpmongo.ParseSort)
"filter": {
"field": "id",
"operator": "eq",
"value": "val",
"value": "val"
}
},
{
"filter": {
"field": "abc",
"operator": "in",
"values": ["a", "b"],
"values": ["a", "b"]
}
}
],
Expand All @@ -88,7 +111,7 @@ sort := payload.Data.Sort.Parse(kpmongo.ParseSort)
}
```
```go
import kpmgo "github.com/raditzlawliet/gokendoparser/adapter/mgo"
import kpmongo "github.com/raditzlawliet/kendoparser/parser/kpmongo"
// just for information
// you can use gorilla mux or knot
var k = k *knot.WebContext
Expand All @@ -97,7 +120,7 @@ var k = k *knot.WebContext
payload := &KendoRequest{}
k.GetPayload(payload)

// Usually payload the struct will be this
// Usually payload the struct will be like this
payload := KendoRequest {
Data: KendoData{
Filter: KendoFilter{
Expand All @@ -113,48 +136,95 @@ payload := KendoRequest {
},
}

filter := payload.Data.Filter.Parse(kpmongo.ParseFilter)
sort := payload.Data.Sort.Parse(kpmongo.ParseSort)
filter := payload.Data.Filter.Parse(kpmongo.FilterParser)
sort := payload.Data.Sort.Parse(kpmongo.SortParser)
```
#### Available Parser & Operator Manager - Filters
- [kpmongo - mongo-go-driver](./parser/mongo)
- equal, notequal, equaldate, notequaldate, contain, notcontain, in, notin, gt, lt, gte, lte, gtdate, ltdate, gtedate, ltedate, exists, dateexists, between
- [kpdbox - eaciit/dbox](./parser/dbox)
- equal, notequal, contain, notcontain, in, gt, lt, gte, lte, gtedate, ltedate, exists, between
- [kpdboxpipe - eaciit/dbox](./parser/dboxpipe)
- equal, notequal, contain, notcontain, in, gt, lt, gte, lte, gtedate, ltedate, exists, between
- [kpdbflex - sebar/dbflex](./parser/dbflex)
- equal, notequal, contain, notcontain, in, gt, lt, gte, lte, gtedate, ltedate, exists, between
- [kpxorm - xorm/builder](./parser/xorm)
- equal, notequal, contain, notcontain, in, gt, lt, gte, lte, gtedate, ltedate, exists, between

#### Operator Manager
_Operator Manager_ mainly used for filter parser to parsing the data based on operator. In available parser they also have each _Operator Manager_.
You also can create your own _Operator Manager_ and you can also set scoped _Operator Manager_ for spesific payload

- Extending Existing Operator Manager

### Extend & Hook custom operator handler
By default, package already registerd with basic operator such as
- Equal
- Not Equal
- Contain
- Not Contain
- In
- Gte
- Lte
- Gte Date
- Lte Date
- Exists

But if you want to add custom operator that didn't exists yet, you can register in manually (for sample you can see [operator.go](adapter/mongo/operator.go)). Please ensure the return must be same with other operator each adapter. Each adapter have operatorManager that helping you to register into each adapter parser
```go
type Operator interface {
Filter(KendoFilter) interface{}
import kpmongo "github.com/raditzlawliet/kendoparser/parser/kpmongo"

// Create the func
func IsOne(kf kendoparser.Filter) interface{} {
return bson.M{kf.Field: bson.M{"$eq": 1}}
}

type EqualOp struct{}
// Assign into Exisiting Operator Manager
kpmongo.OperatorManager.RegisterOperator(IsOne, "isone")

// Filter Filter
func (EqualOp) Filter(kf gokendoparser.KendoFilter) interface{} {
if kf.IgnoreCase {
return EqCi{kf.Field: kf.Value}
}
return builder.Eq{kf.Field: kf.Value}
// Example kendo json request
"filter": {
"field": "id",
"operator": "isone"
}

func register() {
operatorManager.RegisterOperator(equalOp, "eq", "equal")
// Parse
request := struct {
Filter kp.Filter,
}{}
filter := request.Filter.Parse(kpmongo.FilterParser)

// Result
{"id" : {"$eq": 1}}
```

- Creating Your own Operator Manager

Usually when you try to create your own Operator Manager, you should create your own Parser. if the parser already existed, i recommended you use the existing Operator Manager.

```go
// creating global package variable
var (
// OperatorManager of Mongo Parser
OperatorManager = new(kendoparser.OperatorManager)
// Operator bundle of Mongo Parser
Operator = OperatorBundle{}
)

// Wrapper Bundle, so you can put all the func filter into this struct
type OperatorBundle struct{}

// Register when import
func init() {
RegisterOperator()
}

// Registration Process
func RegisterOperator() {
OperatorManager.SetDefaultOperator(Operator.Equal)
OperatorManager.RegisterOperator(Operator.Equal, "eq", "equal")
}

// Some Filter
func (o *OperatorBundle) Equal(kf kendoparser.Filter) interface{} {
if value, ok := kf.Value.(string); ok && kf.IgnoreCase {
value := regexp.QuoteMeta(value)
return bson.M{kf.Field: primitive.Regex{Pattern: "^" + strings.ToLower(value) + "$", Options: "i"}}
}
return bson.M{kf.Field: bson.M{"$eq": kf.Value}}
}
```

### Transforming filter
#### Transforming filter
Need modify your field? lowercase all field before processing? don't worry, you can use Transform to modify and apply to your all field. See [kendo_test.go](kendo_test.go)) for more uses
```go
import kpmgo "github.com/raditzlawliet/gokendoparser/adapter/mgo"
import kpmongo "github.com/raditzlawliet/kendoparser/parser/kpmongo"

kendoFilter := KendoFilter{}

Expand All @@ -172,16 +242,16 @@ kendoFilter.Transform(transformIDMongo) // only current filter
kendoFilter.TransformAll(transformIDMongo) // include filters

// chaining is possible
kendoFilter.TransformFieldAll(strings.ToLower).TransformAll(transformIDMongo).Parse(kpmongo.ParseFilter)
kendoFilter.TransformFieldAll(strings.ToLower).TransformAll(transformIDMongo).Parse(kpmongo.FilterParser)

```

### Custom pre-filter
You can also add custom single handler before building filter by registered operator. This approach you can add custom direct filter within loop filter. pre-filter it self act same like parser, so you can chain the filter with other filter. But if your pre-filter already return value, the last parse only act return the value
#### Additional pre-parse filter
You can also add additional single handler before building filter by registered operator. This approach you can add custom direct filter within loop filter. pre-filter it self act same like parser, so you can chain the filter with other filter. But if your pre-filter already return value, the last parse only act return the value
```go
import kpmgo "github.com/raditzlawliet/gokendoparser/adapter/mgo"
import kpmongo "github.com/raditzlawliet/kendoparser/parser/kpmongo"

beforeFilter := func (kf *KendoFilter) interface{} {
beforeParser := func (kf *KendoFilter) interface{} {
return nil
}

Expand All @@ -192,11 +262,12 @@ resultFilter := kendoFilter.TransformAllField(strings.ToLower).
kf.Field = "_id"
}
}).
BeforeParse(beforeFilter).
Parse(kpmongo.ParseFilter)
AddParse(beforeParser).
Parse(kpmongo.FilterParser)

// reset if needed another
kendoFilter.ResetPreFilter()
kendoFilter.ResetAdditionalParsers()
kendoFilter.ResetAllAdditionalParsers() // Recursive to all filter childs

// dbox pipe
resultFilterPipe := kendoFilter.TransformAllField(strings.ToLower).
Expand All @@ -205,21 +276,23 @@ resultFilterPipe := kendoFilter.TransformAllField(strings.ToLower).
kf.Field = "_id"
}
}).
BeforeParse(beforeFilter).
Parse(kpmongo.ParseFilter)
AddParse(beforeParser).
Parse(kpmongo.FilterParser)
```

## Sort
#### Sort
do you need sort? You can do it easly.
```go
import kpmgo "github.com/raditzlawliet/gokendoparser/adapter/mgo"
import kpmongo "github.com/raditzlawliet/kendoparser/parser/kpmongo"

sort := kData.Sort.Parse(kpmongo.ParseSort)
sort := kData.Sort.Parse(kpmongo.SortParser)
```

## FAQ
- ### go mod tidy keep error `git.eaciitapp.com/sebar/dbflex: no matching versions for query "latest"`
- go mod tidy keep error `git.eaciitapp.com/sebar/dbflex: no matching versions for query "latest"`

This error appear because I use some private database driver in this parser, but you can exclude this using go.mod.

Modify go.mod file, if you dont have the package, just use this dummy in your go.mod, AND If you have the package and using it, replace it into your correct path package:

```replace git.eaciitapp.com/sebar/dbflex => ./pkg/git.eaciitapp.com/sebar/dbflex```
Expand All @@ -232,5 +305,4 @@ Feel free to contribute, don't forget to mention if needed
MIT License

## Author and Contributor
Radityo

Radityo
Loading

0 comments on commit 974d0c3

Please sign in to comment.