Skip to content

Commit

Permalink
Andrei cloud composite spec builder (#285)
Browse files Browse the repository at this point in the history
* Composite with bitmap Import/Export

* Update specs/builder_test.go

* Update specs/builder.go

---------

Co-authored-by: Andrei-cloud <[email protected]>
Co-authored-by: Pavel Gabriel <[email protected]>
  • Loading branch information
3 people authored Oct 6, 2023
1 parent 62da169 commit c741d11
Show file tree
Hide file tree
Showing 2 changed files with 187 additions and 25 deletions.
72 changes: 50 additions & 22 deletions specs/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,31 +114,33 @@ type MessageSpecBuilder interface {
type messageSpecBuilder struct{}

type specDummy struct {
Name string `json:"name,omitempty" xml:"name,omitempty"`
Name string `json:"name,omitempty" xml:"name,omitempty"`
Fields orderedFieldMap `json:"fields,omitempty" xml:"fields,omitempty"`
}

type fieldDummy struct {
Type string `json:"type,omitempty" xml:"type,omitempty"`
Length int `json:"length,omitempty" xml:"length,omitempty"`
Description string `json:"description,omitempty" xml:"description,omitempty"`
Enc string `json:"enc,omitempty" xml:"enc,omitempty"`
Prefix string `json:"prefix,omitempty" xml:"prefix,omitempty"`
Padding *paddingDummy `json:"padding,omitempty" xml:"padding,omitempty"`
Tag *tagDummy `json:"tag,omitempty" xml:"tag,omitempty"`
Subfields map[string]*fieldDummy `json:"subfields,omitempty" xml:"subfields:omitempty"`
Type string `json:"type,omitempty" xml:"type,omitempty"`
Length int `json:"length,omitempty" xml:"length,omitempty"`
Description string `json:"description,omitempty" xml:"description,omitempty"`
Enc string `json:"enc,omitempty" xml:"enc,omitempty"`
Prefix string `json:"prefix,omitempty" xml:"prefix,omitempty"`
Padding *paddingDummy `json:"padding,omitempty" xml:"padding,omitempty"`
Tag *tagDummy `json:"tag,omitempty" xml:"tag,omitempty"`
Subfields map[string]*fieldDummy `json:"subfields,omitempty" xml:"subfields:omitempty"`
Bitmap *fieldDummy `json:"bitmap,omitempty" xml:"bitmap,omitempty"`
DisableAutoExpand bool `json:"disableAutoExpand,omitempty" xml:"disableAutoExpand,omitempty"`
}

type paddingDummy struct {
Type string `json:"type" xml:"type"`
Pad string `json:"pad" xml:"pad"`
Pad string `json:"pad" xml:"pad"`
}

type tagDummy struct {
Length int `json:"length,omitempty" xml:"length,omitempty"`
Enc string `json:"enc,omitempty" xml:"enc,omitempty"`
Length int `json:"length,omitempty" xml:"length,omitempty"`
Enc string `json:"enc,omitempty" xml:"enc,omitempty"`
Padding *paddingDummy `json:"padding,omitempty" xml:"padding,omitempty"`
Sort string `json:"sort,omitempty" xml:"sort,omitempty"`
Sort string `json:"sort,omitempty" xml:"sort,omitempty"`
}

func importField(dummyField *fieldDummy, index string) (*field.Spec, error) {
Expand Down Expand Up @@ -177,17 +179,30 @@ func importField(dummyField *fieldDummy, index string) (*field.Spec, error) {
fieldSpec.Subfields[key] = constructor(subfieldSpec)
}

fieldSpec.Tag = &field.TagSpec{
Length: dummyField.Tag.Length,
if dummyField.Tag != nil {
fieldSpec.Tag = &field.TagSpec{
Length: dummyField.Tag.Length,
}
fieldSpec.Tag.Enc = EncodingsExtToInt[dummyField.Tag.Enc]
if dummyField.Tag.Padding != nil {
if padderConstructor := PaddersExtToInt[dummyField.Tag.Padding.Type]; padderConstructor != nil {
fieldSpec.Tag.Pad = padderConstructor(dummyField.Tag.Padding.Pad)
}
}
fieldSpec.Tag.Sort = SortExtToInt[dummyField.Tag.Sort]
}
fieldSpec.Tag.Enc = EncodingsExtToInt[dummyField.Tag.Enc]
if dummyField.Tag.Padding != nil {
if padderConstructor := PaddersExtToInt[dummyField.Tag.Padding.Type]; padderConstructor != nil {
fieldSpec.Tag.Pad = padderConstructor(dummyField.Tag.Padding.Pad)

if dummyField.Bitmap != nil {
bitmapSpec, err := importField(dummyField.Bitmap, "field bitmap")
if err != nil {
return nil, err
}

fieldSpec.Bitmap = field.NewBitmap(bitmapSpec)
}
fieldSpec.Tag.Sort = SortExtToInt[dummyField.Tag.Sort]

}
fieldSpec.DisableAutoExpand = dummyField.DisableAutoExpand
return fieldSpec, nil
}

Expand Down Expand Up @@ -218,7 +233,11 @@ func (builder *messageSpecBuilder) ImportJSON(raw []byte) (*iso8583.MessageSpec,
}
constructor := FieldConstructor[dummyField.Type]
if constructor == nil {
return nil, fmt.Errorf("no constructor for filed type: %s for field: %d", dummyField.Type, index)
return nil, fmt.Errorf(
"no constructor for filed type: %s for field: %d",
dummyField.Type,
index,
)
}
spec.Fields[index] = constructor(fieldSpec)
}
Expand Down Expand Up @@ -278,7 +297,16 @@ func exportField(internalField field.Field) (*fieldDummy, error) {
}
dummyField.Tag = tag
}

if spec.Bitmap != nil {
bitmap, err := exportField(spec.Bitmap)
if err != nil {
return nil, err
}
dummyField.Bitmap = bitmap
}
}
dummyField.DisableAutoExpand = spec.DisableAutoExpand

return dummyField, nil
}
Expand All @@ -304,7 +332,6 @@ func exportTag(tag *field.TagSpec) (*tagDummy, error) {
dummy.Sort = getFunctionName(tag.Sort)
}
return dummy, nil

}

func exportPad(pad padding.Padder) (*paddingDummy, error) {
Expand All @@ -317,6 +344,7 @@ func exportPad(pad padding.Padder) (*paddingDummy, error) {
}
return nil, fmt.Errorf("unknown padding type: %s", paddingType)
}

func exportEnc(enc encoding.Encoder) (string, error) {
// set encoding
encType := reflect.TypeOf(enc).Elem().Name()
Expand Down
140 changes: 137 additions & 3 deletions specs/builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import (
)

func TestBuilder(t *testing.T) {

asciiJson, err := Builder.ExportJSON(Spec87ASCII)
require.NoError(t, err)

Expand All @@ -31,7 +30,6 @@ func TestBuilder(t *testing.T) {
require.NoError(t, err)

require.Exactly(t, Spec87Hex.Name, hexSpec.Name)

}

func TestExampleJSONSpec(t *testing.T) {
Expand Down Expand Up @@ -87,7 +85,8 @@ func TestSpecWithCompositeFields(t *testing.T) {
Pref: prefix.EBCDIC.Fixed,
Pad: padding.Left('0'),
}),
}}),
},
}),
30: field.NewNumeric(&field.Spec{
Length: 5,
Description: "field key that is not next number",
Expand All @@ -114,3 +113,138 @@ func TestSpecWithCompositeFields(t *testing.T) {

require.Exactly(t, testSpec, importedSpec)
}

func TestSpecWithCompositeBitmapedFields(t *testing.T) {
specJSON := []byte(`
{
"name": "TEST Spec",
"fields": {
"1": {
"type": "Composite",
"length": 255,
"description": "Private use field",
"prefix": "ASCII.LL",
"bitmap": {
"type": "Bitmap",
"length": 8,
"description": "Bitmap",
"enc": "HexToASCII",
"prefix": "Hex.Fixed",
"disableAutoExpand": true
},
"subfields": {
"1": {
"type": "String",
"length": 2,
"description": "Cardholder certificate Serial Number",
"enc": "ASCII",
"prefix": "ASCII.Fixed"
},
"2": {
"type": "String",
"length": 2,
"description": "Merchant certificate Serial Number",
"enc": "ASCII",
"prefix": "ASCII.Fixed"
},
"3": {
"type": "String",
"length": 2,
"description": "Transaction ID",
"enc": "ASCII",
"prefix": "ASCII.Fixed"
},
"4": {
"type": "String",
"length": 20,
"description": "CAVV",
"enc": "ASCII",
"prefix": "ASCII.Fixed"
},
"5": {
"type": "String",
"length": 20,
"description": "CAVV",
"enc": "ASCII",
"prefix": "ASCII.Fixed"
},
"6": {
"type": "String",
"length": 2,
"description": "Cardholder certificate Serial Number",
"enc": "ASCII",
"prefix": "ASCII.Fixed"
},
"7": {
"type": "String",
"length": 2,
"description": "Merchant certificate Serial Number",
"enc": "ASCII",
"prefix": "ASCII.Fixed"
},
"8": {
"type": "String",
"length": 2,
"description": "Transaction ID",
"enc": "ASCII",
"prefix": "ASCII.Fixed"
},
"9": {
"type": "String",
"length": 20,
"description": "CAVV",
"enc": "ASCII",
"prefix": "ASCII.Fixed"
},
"10": {
"type": "String",
"length": 6,
"description": "CVV2",
"enc": "ASCII",
"prefix": "ASCII.Fixed"
}
}
}
}
}`)

spec, err := Builder.ImportJSON(specJSON)
require.NoError(t, err)

data := struct {
F1 *field.String
F2 *field.String
F3 *field.String
F4 *field.String
F5 *field.String
F6 *field.String
F7 *field.String
F8 *field.String
F9 *field.String
F10 *field.String
}{
F10: field.NewStringValue("11 456"),
}

compositeRestored := field.NewComposite(spec.Fields[1].Spec())
err = compositeRestored.Marshal(&data)
require.NoError(t, err)

packed, err := compositeRestored.Pack()
require.NoError(t, err)
require.Equal(t, "22004000000000000011 456", string(packed))

exportedJSON, err := Builder.ExportJSON(spec)
require.NoError(t, err)

spec, err = Builder.ImportJSON(exportedJSON)
require.NoError(t, err)

compositeRestored = field.NewComposite(spec.Fields[1].Spec())
err = compositeRestored.Marshal(&data)
require.NoError(t, err)

packed, err = compositeRestored.Pack()
require.NoError(t, err)
require.Equal(t, "22004000000000000011 456", string(packed))
}

0 comments on commit c741d11

Please sign in to comment.