diff --git a/doc/src/asciidoc/book.adoc b/doc/src/asciidoc/book.adoc index 6bb4558e7b..3949c00e65 100644 --- a/doc/src/asciidoc/book.adoc +++ b/doc/src/asciidoc/book.adoc @@ -2,8 +2,9 @@ jPOS Extended Edition ===================== :author: Alejandro Revilla :email: apr@jpos.org -:revnumber: 2.0.1 -:jposee_version: 2.0.1 +:revnumber: 2.0.9 +:jposee_version: 2.0.9 +:toc: Introduction ============ @@ -56,6 +57,10 @@ include::module_client_simulator.adoc[] include::module_sshd.adoc[] +== Contributed modules + +include::module_fsdmsgX.adoc[] + //------------------------------------------------------------ // ** UNIMPLEMENTED ** // @@ -74,5 +79,5 @@ Appendices include::appendix_copyright.adoc[] include::appendix_license.adoc[] include::appendix_CLA.adoc[] -include::appendix_CCLA.adoc[] +// include::appendix_CCLA.adoc[] diff --git a/doc/src/asciidoc/module_fsdmsgX.adoc b/doc/src/asciidoc/module_fsdmsgX.adoc new file mode 100644 index 0000000000..aab487c3d1 --- /dev/null +++ b/doc/src/asciidoc/module_fsdmsgX.adoc @@ -0,0 +1,149 @@ +=== FSDMsgX + +[frame="none",cols="20%,80%"] +|================================================================= +|*What:*| This field/mesage packager can be used to wire a message parser with java code. Its utility library to enable you to parse grammar usually used by text (can be binary as well) messages +that are field separator delimited, fixed length, branching based on data +parsed, looking ahead in the stream for a specific byte and base future +parsing decisions. Provides out of the box PCI compliance and ability to add java objects to meet you compliance needs. +|*When:*| Available as of jPOS-EE 2.0.9 +|*Who:*| The jPOS.org team (contributed by @chhil) +|*How:*| Posted by the jPOS-EE team. +|*Where:*| Directory modules/fsdpackager available in the jPOS-EE main git repository +|*Why:*| When schema based FSD does not meet your parsing needs to write more complex parsing rules. +|*Status:*| Production grade +|*Dependencies:*| module jpos +|*License:*| <> +|================================================================= + +==== Using the packagers + +===== FixedFieldPackager + +Consider a specification that states field 1 is a fixed field of 6 and field 2 is a fixed stram of 3 bytes. +Stream of bytes=123456AB +If the specification is followed: +Field1 = 123456 +Field2 = AB + +.FixedFieldPackager Usage [unpacking raw bytes] +[source,java] +------------- + + FSDMsgX msg = new FSDMsgX("Example1"); + FixedFieldPackager field1 = new FixedFieldPackager( + "Field1", 6, AsciiInterpreter.INSTANCE + ); + FixedFieldPackager field2 = new FixedFieldPackager( + "Field2", 2, AsciiInterpreter.INSTANCE + ); + msg.add(field1); + msg.add(field2); + + String s = "123456ABEXTRA";// there are EXTRA bytes in the stream + + int offset = msg.unpack(s.getBytes()); + System.out.println("Offset="+offset); + System.out.println("Field1="+msg.get("Field1")); + System.out.println("Field2="+msg.get("Field2")); + System.out.println(msg.dump("dump")); + System.out.println(msg.getParserTree("tree>")); + System.out.println(msg.hexDump("")); + +------------- + +*Output* + +[source,xml] +------------ +Offset=8 +Field1=123456 +Field2=AB +dump +dump +dump +dump +tree>[Example1] +tree>Field [Field1] : Fixed [6] : 123456 +tree>Field [Field2] : Fixed [2] : AB +0000 31 32 33 34 35 36 41 42 123456AB +------------ + +* Create the main container object FSDMsgX. +* Create the individual field packagers for field1 and field2. +* Add the individual field packagers to the container. +* Call the unpack method on the input bytes to parse the stream. +* The unpac method returns the offset in the stream where the parser has reached, + we parsed a total of 8 bytes, the offset is 8 (its 0 based so its at the 9^th^ + position. + +* Notice the fields are accessible via the containers get method. +* The containers dump method, provides a pretty xml ( the prefix of "dump" to identify it in the output. +* The container has a getParseTree method that display your composite packager. + This will help once you get into complex composite packager. The use of of the + prefix "tree" is used to identify its output. +* The container has a hexdump method that dumps the hex equivalent of the + unpacked stream. Notice EXTRA is not there as there was no rule to unpack it. +* If the input string was s = "123456" then an ISOException would be thrown + telling you precisely what was wrong. org.jpos.iso.ISOException: Field + [Field2] at offset [6]:Expecting 2 bytes found 0 + +.FixedFieldPackager Usage [packing object into bytes] +[source,java] +------------- + FSDMsgX msg = new FSDMsgX("Example1"); + FixedFieldPackager field1 = new FixedFieldPackager( + "Field1", 6, AsciiInterpreter.INSTANCE + ); + FixedFieldPackager field2 = new FixedFieldPackager( + "Field2", 2, AsciiInterpreter.INSTANCE + ); + + msg.add(field1); + msg.add(field2); + + msg.set("Field1", "ABCDEF"); + msg.set("Field2", "12"); + + byte[] outStream = msg.pack(); + + System.out.println(msg.dump("dump")); + System.out.println(msg.getParserTree("tree>")); + System.out.println(msg.hexDump("")); + System.out.println(ISOUtil.hexdump(outStream)); +------------- + +*Output* +[source,xml] +------------ +dump +dump +dump +dump +tree>[Example1] +tree>Field [Field1] : Fixed [6] : ABCDEF +tree>Field [Field2] : Fixed [2] : 12 +0000 41 42 43 44 45 46 31 32 ABCDEF12 +0000 41 42 43 44 45 46 31 32 ABCDEF12 +------------ + +* Set the fields in the container. +* Call the unpack method on the container to serialize the object into a byte + array. +* You can verify that data looks accurate in dump method. +* You can verify that the parser parsed it correctly. +* You can verify the hexdump of the actual packed vyte array outstream is the + same as the hexdump of the container. + +===== VariableFieldPackager +Used when the size of the field is variable and needs a delimiter to indicate +the end of the field. + +Consider a specification that indicates a field FirstName can have a maximulm +of 20 characters and will be terminate/delimited by a semi colon followed by a +Lastname with a maximum of 10 characters terminated by a period. The delimiter +is important because I could have a name Tom, Tommy, Thomas to indicate the end +of a name a delimiter is needed. If I did bot have a FirstName, a semi colon +would be needed to indicate there is no first name. + + diff --git a/modules/fsdmsgx/FSDMsgX.pdf b/modules/fsdmsgx/FSDMsgX.pdf new file mode 100644 index 0000000000..716b96caa9 Binary files /dev/null and b/modules/fsdmsgx/FSDMsgX.pdf differ diff --git a/modules/fsdmsgx/build.gradle b/modules/fsdmsgx/build.gradle new file mode 100644 index 0000000000..8d45f3fd17 --- /dev/null +++ b/modules/fsdmsgx/build.gradle @@ -0,0 +1,6 @@ +description = 'jPOS-EE :: FSDMsgX' + +dependencies { + compile libraries.jpos +} + diff --git a/modules/fsdmsgx/src/main/java/com/sample/hsm/HSMMessage.java b/modules/fsdmsgx/src/main/java/com/sample/hsm/HSMMessage.java new file mode 100644 index 0000000000..c710d7cbe2 --- /dev/null +++ b/modules/fsdmsgx/src/main/java/com/sample/hsm/HSMMessage.java @@ -0,0 +1,226 @@ +package com.sample.hsm; + +import java.util.HashMap; +import java.util.Map; + +import org.jpos.fsdpackager.AFSDFieldPackager; +import org.jpos.fsdpackager.BranchFieldPackager; +import org.jpos.fsdpackager.FSDMsgX; +import org.jpos.fsdpackager.FixedFieldPackager; +import org.jpos.fsdpackager.LookAheadPackager; +import org.jpos.fsdpackager.OptionalPackager; +import org.jpos.fsdpackager.compliance.TrackDataCompliance; +import org.jpos.iso.AsciiInterpreter; +import org.jpos.iso.ISOException; +import org.jpos.iso.ISOUtil; + +public class HSMMessage { + + public FSDMsgX getFSDMessage() { + + FSDMsgX message = new FSDMsgX("HSM"); + FixedFieldPackager stan = new FixedFieldPackager("stan", 4, AsciiInterpreter.INSTANCE); + message.add(stan); + + FixedFieldPackager command = new FixedFieldPackager("command", 2, AsciiInterpreter.INSTANCE); + message.add(command); + + Map commandCases = new HashMap(); + commandCases.put("A0", getA0Packager()); + commandCases.put("A1", getA1Packager()); + commandCases.put("A6", getA6Packager()); + commandCases.put("FA", getFAPackager()); + + BranchFieldPackager branchCommand = new BranchFieldPackager("commandBrancher", "command", commandCases, null); + + message.add(branchCommand); + return message; + + } + + private static AFSDFieldPackager getFAPackager() { + FixedFieldPackager f1 = new FixedFieldPackager("zmk-scheme", 1, AsciiInterpreter.INSTANCE); + FixedFieldPackager f2 = new FixedFieldPackager("zmk", 32, AsciiInterpreter.INSTANCE); + FixedFieldPackager f3 = new FixedFieldPackager("import-key-scheme", 1, AsciiInterpreter.INSTANCE); + FixedFieldPackager f4 = new FixedFieldPackager("key-to-import-under-zmk", 32, AsciiInterpreter.INSTANCE); + FixedFieldPackager f5 = new FixedFieldPackager("mode", 1, AsciiInterpreter.INSTANCE); + OptionalPackager f6 = new OptionalPackager("optiona-variant", + new FixedFieldPackager("attalla-variant", 1, AsciiInterpreter.INSTANCE)); + + FSDMsgX optionalGrp1 = new FSDMsgX("OptionalGroup1"); + AFSDFieldPackager semicolon = new FixedFieldPackager("delimiter",";",AsciiInterpreter.INSTANCE); + AFSDFieldPackager reserved1 = new FixedFieldPackager("Reserved-1","O",AsciiInterpreter.INSTANCE); + AFSDFieldPackager keySchemeLMK = new FixedFieldPackager("key-scheme-lmk",1,AsciiInterpreter.INSTANCE); + AFSDFieldPackager keyCheckValue = new FixedFieldPackager("key-check-value-len",1,AsciiInterpreter.INSTANCE); + optionalGrp1.add(semicolon); + optionalGrp1.add(reserved1); + optionalGrp1.add(keySchemeLMK); + optionalGrp1.add(keyCheckValue); + LookAheadPackager determineGrp1 = new LookAheadPackager("LAGRP1", 0, new Byte((byte)';') ,optionalGrp1, null, new String[]{"key-scheme-lmk","key-check-value-len"}, null); + + FSDMsgX optionalGrp2 = new FSDMsgX("OptionalGroup2"); + + AFSDFieldPackager lmkid = new FixedFieldPackager("LMK-ID",2,AsciiInterpreter.INSTANCE); + AFSDFieldPackager percent = new FixedFieldPackager("delimiter-2","%",AsciiInterpreter.INSTANCE); + optionalGrp2.add(percent); + optionalGrp2.add(lmkid); + LookAheadPackager determineGrp2 = new LookAheadPackager("LAGRP2", 0, new Byte((byte)'%') ,optionalGrp2, null, new String[]{"LMK-ID"}, null); + + + FSDMsgX container = new FSDMsgX("TranslateZPKReq-FA"); + container.add(f1); + container.add(f2); + container.add(f3); + container.add(f4); + container.add(f5); + container.add(f6); + container.add(determineGrp1); + container.add(determineGrp2); + + return container; + + } + + private static FSDMsgX getA0Packager() { + + FixedFieldPackager f1 = new FixedFieldPackager("mode", 1, AsciiInterpreter.INSTANCE); + FixedFieldPackager f2 = new FixedFieldPackager("key-type", 3, AsciiInterpreter.INSTANCE); + FixedFieldPackager f3 = new FixedFieldPackager("key-scheme-key-under-lmk", 1, AsciiInterpreter.INSTANCE); + FixedFieldPackager f4 = new FixedFieldPackager("scheme-zmk-or-tmk", 1, AsciiInterpreter.INSTANCE); + FixedFieldPackager f5 = new FixedFieldPackager("key-zmk-or-tmk", 32, AsciiInterpreter.INSTANCE); + FixedFieldPackager f6 = new FixedFieldPackager("key-scheme-key-under-zmk-or-tmk", 1, AsciiInterpreter.INSTANCE); + + FSDMsgX container = new FSDMsgX("GenerateKeyReq-A0"); + container.add(f1); + container.add(f2); + container.add(f3); + container.add(f4); + container.add(f5); + container.add(f6); + return container; + + } + + private static AFSDFieldPackager getA6Packager() { + FixedFieldPackager f1 = new FixedFieldPackager("key-type", 3, AsciiInterpreter.INSTANCE); + FixedFieldPackager f2 = new FixedFieldPackager("zmk-scheme", 1, AsciiInterpreter.INSTANCE); + FixedFieldPackager f3 = new FixedFieldPackager("zmk", 32, AsciiInterpreter.INSTANCE, new TrackDataCompliance()); + FixedFieldPackager f4 = new FixedFieldPackager("import-key-scheme", 1, AsciiInterpreter.INSTANCE); + FixedFieldPackager f5 = new FixedFieldPackager("key-to-import-under-zmk", 32, AsciiInterpreter.INSTANCE, + new TrackDataCompliance()); + FixedFieldPackager f6 = new FixedFieldPackager("scheme-key-encrpt-under-lmk", 1, AsciiInterpreter.INSTANCE); + OptionalPackager f7 = new OptionalPackager("optiona-variant", + new FixedFieldPackager("attalla-variant", 1, AsciiInterpreter.INSTANCE)); + + FSDMsgX container = new FSDMsgX("ImportKeyReq-A6"); + container.add(f1); + container.add(f2); + container.add(f3); + container.add(f4); + container.add(f5); + container.add(f6); + container.add(f7); + return container; + + } + + private static AFSDFieldPackager getA1Packager() { + + FixedFieldPackager f0 = new FixedFieldPackager("error", 2, AsciiInterpreter.INSTANCE); + + FixedFieldPackager f1 = new FixedFieldPackager("scheme-key-under-lmk", 1, AsciiInterpreter.INSTANCE); + FixedFieldPackager f2 = new FixedFieldPackager("key-under-lmk", 32, AsciiInterpreter.INSTANCE); + FixedFieldPackager f3 = new FixedFieldPackager("scheme-key-under-zmk", 1, AsciiInterpreter.INSTANCE); + FixedFieldPackager f4 = new FixedFieldPackager("key-under-zmk", 32, AsciiInterpreter.INSTANCE); + FixedFieldPackager f5 = new FixedFieldPackager("check-value", 6, AsciiInterpreter.INSTANCE); + + FSDMsgX container = new FSDMsgX("GenerateKeyRsp-A1"); + container.add(f0); + container.add(f1); + container.add(f2); + container.add(f3); + container.add(f4); + container.add(f5); + return container; + } + + public static void main(String[] args) throws ISOException { + HSMMessage m = new HSMMessage(); +// FSDMsgX fsd1 = m.getFSDMessage(); +// fsd1.set("stan", "1234"); +// fsd1.set("command", "A0"); +// fsd1.set("mode", "1"); +// fsd1.set("key-type", "001"); +// fsd1.set("key-scheme-key-under-lmk", "A"); +// fsd1.set("scheme-zmk-or-tmk", "B"); +// fsd1.set("key-zmk-or-tmk", ISOUtil.padleft("", 32, 'F')); +// fsd1.set("key-scheme-key-under-zmk-or-tmk", "C"); +// byte[] outStream = fsd1.pack(); +// System.out.println(ISOUtil.hexdump(outStream)); +// System.out.println(fsd1.dump("")); +// System.out.println(fsd1.getParserTree("")); +// +// FSDMsgX fsd3 = m.getFSDMessage(); +// fsd3.set("stan", "1234"); +// fsd3.set("command", "A6"); +// fsd3.set("key-type", "001"); +// fsd3.set("zmk-scheme", "A"); +// fsd3.set("zmk", ISOUtil.padleft("", 32, 'A')); +// fsd3.set("import-key-scheme", "X"); +// fsd3.set("key-to-import-under-zmk", ISOUtil.padleft("", 32, 'B')); +// fsd3.set("scheme-key-encrpt-under-lmk", "C"); +// fsd3.set("attalla-variant", "V"); +// byte[] outStream3 = fsd3.pack(); +// System.out.println(ISOUtil.hexdump(outStream3)); +// System.out.println(fsd3.dump("")); +// System.out.println(fsd3.getParserTree("")); +// +// FSDMsgX fsd4 = m.getFSDMessage(); +// fsd4.set("stan", "1234"); +// fsd4.set("command", "A6"); +// fsd4.set("key-type", "001"); +// fsd4.set("zmk-scheme", "A"); +// fsd4.set("zmk", ISOUtil.padleft("", 32, 'A')); +// fsd4.set("import-key-scheme", "X"); +// fsd4.set("key-to-import-under-zmk", ISOUtil.padleft("", 32, 'B')); +// fsd4.set("scheme-key-encrpt-under-lmk", "C"); +// byte[] outStream4 = fsd4.pack(); +// System.out.println(ISOUtil.hexdump(outStream4)); +// System.out.println(fsd4.dump("")); +// System.out.println(fsd4.getParserTree("")); + + + FSDMsgX fsd2 = m.getFSDMessage(); + fsd2.set("stan", "1234"); + fsd2.set("command", "FA"); + fsd2.set("zmk-scheme", "A"); + fsd2.set("zmk", ISOUtil.padleft("", 32, 'A')); + fsd2.set("import-key-scheme", "B"); + fsd2.set("key-to-import-under-zmk",ISOUtil.padleft("", 32, 'A')); + fsd2.set("mode", "1"); + fsd2.set("attalla-variant", "V"); + + //optional group fields + fsd2.set("key-scheme-lmk", "U"); + fsd2.set("key-check-value-len", "0"); + + //optional grp2 field + fsd2.set("LMK-ID", "00"); + + + + byte[] outStream2 = fsd2.pack(); + System.out.println(ISOUtil.hexdump(outStream2)); + System.out.println(fsd2.dump("")); + System.out.println(fsd2.getParserTree("")); + + +// FSDMsgX mess = m.getFSDMessage(); +// mess.unpack(outStream2); +// System.out.println(mess.dump("")); +// System.out.println(mess.getParserTree("")); + + + } + +} diff --git a/modules/fsdmsgx/src/main/java/org/jpos/fsdpackager/AFSDFieldPackager.java b/modules/fsdmsgx/src/main/java/org/jpos/fsdpackager/AFSDFieldPackager.java new file mode 100644 index 0000000000..4d05b248df --- /dev/null +++ b/modules/fsdmsgx/src/main/java/org/jpos/fsdpackager/AFSDFieldPackager.java @@ -0,0 +1,78 @@ +/* + * jPOS Project [http://jpos.org] + * Copyright (C) 2000-2015 Alejandro P. Revilla + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.jpos.fsdpackager; + +import java.util.Map; + +import org.jpos.iso.ISOException; + +public class AFSDFieldPackager implements IFSDFieldPackager { + + private String name; + + + /* (non-Javadoc) + * @see org.jpos.fsdpackager.IFSDFieldPackager#pack(java.util.Map) + */ + public byte[] pack(Map setfields) throws ISOException { + // TODO Auto-generated method stub + return null; + } + + public String getValue() { + // TODO Auto-generated method stub + return null; + } + + public void setValue(String value) { + // TODO Auto-generated method stub + + } + + public int unpack(byte[] inStream, int offset, Map fields) throws ISOException { + // TODO Auto-generated method stub + return 0; + } + + public String getName() { + return name; + } + + public void setName(String fieldName) { + this.name = fieldName; + } + + public String dump(String prefix, Map setfields) { + + return ""; + + } + + public byte[] hexDump(String prefix,Map setfields) { + // TODO Auto-generated method stub + return null; + } + + public String getParserTree(String prefix) { + // TODO Auto-generated method stub + return null; + } + + +} diff --git a/modules/fsdmsgx/src/main/java/org/jpos/fsdpackager/BranchFieldPackager.java b/modules/fsdmsgx/src/main/java/org/jpos/fsdpackager/BranchFieldPackager.java new file mode 100644 index 0000000000..f7463336e6 --- /dev/null +++ b/modules/fsdmsgx/src/main/java/org/jpos/fsdpackager/BranchFieldPackager.java @@ -0,0 +1,195 @@ +/* + * jPOS Project [http://jpos.org] + * Copyright (C) 2000-2015 Alejandro P. Revilla + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.jpos.fsdpackager; + +import java.util.Map; + +import org.jpos.iso.ISOException; + +/** + * @author Murtuza + * + */ +public class BranchFieldPackager extends AFSDFieldPackager { + + private String switchField; + private Map switchCases; + private AFSDFieldPackager defaultCase; + + /** + * @param name + * Name of this field. + * @param switchField + * Name of the field whose parsed value value will be used to + * determine packager to follow. + * @param switchCases + * A map containing values to packager mapping. + * @param defaultCase + * If the map cannot find the value in the map, uses this default + * packager to handle it. + */ + public BranchFieldPackager(String name, String switchField, Map switchCases, + AFSDFieldPackager defaultCase) { + + this.setName(name); + this.switchField = switchField; + this.switchCases = switchCases; + this.defaultCase = defaultCase; + + } + + /* + * (non-Javadoc) + * + * @see org.jpos.fsdpackager.AFSDFieldPackager#unpack(byte[], int, + * java.util.Map) + */ + @Override + public int unpack(byte[] inStream, int offset, Map fields) throws ISOException { + + String fieldValue = fields.get(switchField); + if (fieldValue == null) { + if (defaultCase != null) { + + offset = defaultCase.unpack(inStream, offset, fields); + fields.put(defaultCase.getName(), defaultCase.getValue()); + } + } else { + AFSDFieldPackager temp = switchCases.get(fieldValue); + if (temp == null) { + if (defaultCase != null) { + offset = defaultCase.unpack(inStream, offset, fields); + fields.put(defaultCase.getName(), defaultCase.getValue()); + } + } else { + offset = temp.unpack(inStream, offset, fields); + fields.put(temp.getName(), temp.getValue()); + } + } + + return offset; + } + + /* + * (non-Javadoc) + * + * @see org.jpos.fsdpackager.AFSDFieldPackager#pack(java.util.Map) + */ + @Override + public byte[] pack(Map fields) throws ISOException { + + String value = fields.get(switchField); + + if (value == null) { + if (defaultCase != null) { + defaultCase.setValue(fields.get(defaultCase.getName())); + return defaultCase.pack(fields); + } + return null; + } + AFSDFieldPackager selectedPackager = switchCases.get(value); + if (selectedPackager == null) { + + if (defaultCase != null) { + defaultCase.setValue(fields.get(defaultCase.getName())); + return defaultCase.pack(fields); + } + return null; + + } + selectedPackager.setValue(fields.get(selectedPackager.getName())); + return selectedPackager.pack(fields); + + } + + @Override + public String getValue() { + // TODO Auto-generated method stub + return ""; + } + + @Override + public void setValue(String value) { + // TODO Auto-generated method stub + + } + + @Override + public String dump(String prefix, Map setfields) { + + String fieldValue = setfields.get(switchField); + if (fieldValue == null) { + if (defaultCase != null) { + + return defaultCase.dump(prefix, setfields); + } + } else { + AFSDFieldPackager temp = switchCases.get(fieldValue); + if (temp == null) { + if (defaultCase != null) { + return defaultCase.dump(prefix, setfields); + } + } else { + + return temp.dump(prefix, setfields); + } + } + return ""; + + } + + /** + * Provides a description of this parser rule. + * e.g. output + *
+	 * Field [F1] : Fixed [5] : ABCDE
+	 * Field [F2] : Fixed [2] : 02
+	 * Field [F3] : [Branch]
+	 * switch (F2)
+	 * 	01:
+	 * 		Field [F4] : Fixed [3] 
+	 * 	02:
+	 * 		Field [F5] : Fixed [4] : 4444
+	 * 	default:
+	 * 
+ */ + @Override + public String getParserTree(String prefix) { + + String cases = ""; + if (switchCases == null) { + + cases += "[Not Set]" + System.lineSeparator(); + } else { + for (Map.Entry entry : switchCases.entrySet()) { + + AFSDFieldPackager fPkgr = entry.getValue(); + + cases += "\t\t" + entry.getKey() + ":" + System.lineSeparator() + fPkgr.getParserTree("\t\t\t"); + + } + } + cases += "\t\tdefault:" + System.lineSeparator() + ((defaultCase != null) + ? System.lineSeparator() + defaultCase.getParserTree("\t\t\t") : "\t\t\t[Not Set]"); + + return String.format("%sField [%s] : [Branch]%n" + "\tswitch (%s)%n" + "%s", prefix, getName(), switchField, + cases); + } + +} diff --git a/modules/fsdmsgx/src/main/java/org/jpos/fsdpackager/FSDField.java b/modules/fsdmsgx/src/main/java/org/jpos/fsdpackager/FSDField.java new file mode 100644 index 0000000000..d48eb89064 --- /dev/null +++ b/modules/fsdmsgx/src/main/java/org/jpos/fsdpackager/FSDField.java @@ -0,0 +1,38 @@ +/* + * jPOS Project [http://jpos.org] + * Copyright (C) 2000-2015 Alejandro P. Revilla + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.jpos.fsdpackager; + +public class FSDField { + + private String name; + private String value; + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + public String getValue() { + return value; + } + public void setValue(String value) { + this.value = value; + } + +} diff --git a/modules/fsdmsgx/src/main/java/org/jpos/fsdpackager/FSDMsgX.java b/modules/fsdmsgx/src/main/java/org/jpos/fsdpackager/FSDMsgX.java new file mode 100644 index 0000000000..5a0a63ad8c --- /dev/null +++ b/modules/fsdmsgx/src/main/java/org/jpos/fsdpackager/FSDMsgX.java @@ -0,0 +1,259 @@ +/* + * jPOS Project [http://jpos.org] + * Copyright (C) 2000-2015 Alejandro P. Revilla + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.jpos.fsdpackager; + +import java.util.LinkedHashMap; +import java.util.Map; + +import org.jpos.iso.ISOException; +import org.jpos.iso.ISOUtil; + +public class FSDMsgX extends AFSDFieldPackager { + + public String dump(String prefix, Map setfields) { + // TODO Auto-generated method stub + return dump(prefix); + } + + private Map fieldPackagers = new LinkedHashMap(); + private Map setfields = new LinkedHashMap(); + + public FSDMsgX(String name) { + setName(name); + } + + private FSDMsgX() { + }; + + public void add(String name, AFSDFieldPackager fsdFieldPackager) { + + getFields().put(name,fsdFieldPackager); + + } + + public void add(AFSDFieldPackager fsdFieldPackager) { + + getFields().put(fsdFieldPackager.getName(), fsdFieldPackager); + + } + @Override + public byte[] pack(Map setfields) throws ISOException { + this.setSetfields(setfields); + return pack(); + + } + + @Override + public int unpack(byte[] inStream, int offset, Map fields) throws ISOException { + // TODO Auto-generated method stub + Map f = getFields(); + + int innerOffset = unpack(inStream, offset); + + for (Map.Entry entry : getSetfields().entrySet()) { + + fields.put(entry.getKey(), entry.getValue()); + } + + return innerOffset; + + } + + public void set(String fieldName, String value) { + + IFSDFieldPackager p = getFields().get(fieldName); + + getSetfields().put(fieldName, value); + if (p != null) + p.setValue(value); + + } + + public String get(String fieldName) { + + return setfields.get(fieldName); + } + + public int unpack(byte[] inStream, int offset) throws ISOException { + + for (Map.Entry entry : getFields().entrySet()) { + + FSDField f = new FSDField(); + f.setName(entry.getKey()); + + offset = entry.getValue().unpack(inStream, offset, getSetfields()); + getSetfields().put(entry.getValue().getName(), entry.getValue().getValue()); + + } + return offset; + + } + + public int unpack(byte[] inStream) throws ISOException { + + int offset = 0; + for (Map.Entry entry : getFields().entrySet()) { + + FSDField f = new FSDField(); + f.setName(entry.getKey()); + + offset = entry.getValue().unpack(inStream, offset, getSetfields()); + getSetfields().put(entry.getValue().getName(), entry.getValue().getValue()); + + } + return offset; + + } + + public byte[] pack() throws ISOException { + + byte[] outStream = null; + for (Map.Entry entry : getFields().entrySet()) { + + byte[] temp = entry.getValue().pack(getSetfields()); + if (temp != null) { + if (outStream == null) { + outStream = temp; + } else { + byte[] outStream2 = new byte[outStream.length + temp.length]; + System.arraycopy(outStream, 0, outStream2, 0, outStream.length); + System.arraycopy(temp, 0, outStream2, outStream.length, temp.length); + outStream = outStream2; + } + } + } + return outStream; + + } + + public String dump(String prefix) { + + StringBuilder sb = new StringBuilder(); + sb.append(String.format("%s%n", prefix, getName())); + String inner_prefix = prefix + "\t"; + for (Map.Entry entry : getFields().entrySet()) { + + sb.append(entry.getValue().dump(inner_prefix, getSetfields())); + + } + sb.append(String.format("%s%n", prefix)); + return sb.toString(); + } + + public String hexDump(String prefix) { + + StringBuilder sb = new StringBuilder(); + byte[] outStream = null; + for (Map.Entry entry : getFields().entrySet()) { + + Map setFieldmap = getSetfields(); + Map fieldPackager = getFields(); + AFSDFieldPackager fPkgr = entry.getValue(); + if (fPkgr instanceof FSDMsgX) { + byte[] innerOutStream = hexDump(prefix, ((FSDMsgX) fPkgr).getSetfields()); + if (innerOutStream != null) { + + if (outStream == null) { + outStream = innerOutStream; + } else { + byte[] outStream2 = new byte[outStream.length + innerOutStream.length]; + System.arraycopy(outStream, 0, outStream2, 0, outStream.length); + System.arraycopy(innerOutStream, 0, outStream2, outStream.length, innerOutStream.length); + outStream = outStream2; + } + + } + + } else { + byte[] temp = entry.getValue().hexDump("", getSetfields()); + if (temp != null) { + if (outStream == null) { + outStream = temp; + } else { + byte[] outStream2 = new byte[outStream.length + temp.length]; + System.arraycopy(outStream, 0, outStream2, 0, outStream.length); + System.arraycopy(temp, 0, outStream2, outStream.length, temp.length); + outStream = outStream2; + } + } + } + + } + sb.append(ISOUtil.hexdump(outStream)); + sb.append(System.lineSeparator()); + return sb.toString(); + + } + + public Map getFields() { + return fieldPackagers; + } + + public void setFields(Map fields) { + this.fieldPackagers = fields; + } + + public Map getSetfields() { + return setfields; + } + + public void setSetfields(Map setfields) { + this.setfields = setfields; + } + + @Override + public byte[] hexDump(String prefix, Map setfields) { + + byte[] outStream = null; + for (Map.Entry entry : fieldPackagers.entrySet()) { + + byte[] temp = entry.getValue().hexDump(prefix, getSetfields()); + if (temp != null) { + if (outStream == null) { + outStream = temp; + } else { + byte[] outStream2 = new byte[outStream.length + temp.length]; + System.arraycopy(outStream, 0, outStream2, 0, outStream.length); + System.arraycopy(temp, 0, outStream2, outStream.length, temp.length); + outStream = outStream2; + } + } + + } + return outStream; + // sb.append(ISOUtil.hexdump(outStream)); + + } + + @Override + public String getParserTree(String prefix) { + StringBuilder sb = new StringBuilder(String.format("%s[%s]%n", prefix,getName())); + + for (Map.Entry entry : getFields().entrySet()) { + + AFSDFieldPackager fPkgr = entry.getValue(); + sb.append(fPkgr.getParserTree(prefix)); + } + + return sb.toString(); + } + + + +} diff --git a/modules/fsdmsgx/src/main/java/org/jpos/fsdpackager/FixedFieldPackager.java b/modules/fsdmsgx/src/main/java/org/jpos/fsdpackager/FixedFieldPackager.java new file mode 100644 index 0000000000..7039e7d73f --- /dev/null +++ b/modules/fsdmsgx/src/main/java/org/jpos/fsdpackager/FixedFieldPackager.java @@ -0,0 +1,165 @@ +/* + * jPOS Project [http://jpos.org] + * Copyright (C) 2000-2015 Alejandro P. Revilla + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.jpos.fsdpackager; + +import java.util.Map; + +import org.jpos.fsdpackager.compliance.APCICompliance; +import org.jpos.fsdpackager.compliance.NoCompliance; +import org.jpos.iso.ISOException; +import org.jpos.iso.ISOUtil; +import org.jpos.iso.Interpreter; + +public class FixedFieldPackager extends AFSDFieldPackager { + + private String value; + Interpreter interpretter; + private int size; + private boolean padLeft = true; + private boolean padright = false; + private Byte padCharacter = new Byte((byte) 0x20); //space + private APCICompliance compliance = new NoCompliance(); + + public FixedFieldPackager(String name,int size,Interpreter interpretter) { + this.interpretter = interpretter; + this.size = size; + this.setName(name); + } + public FixedFieldPackager(String name,int size,Interpreter interpretter, APCICompliance compliance) { + + this(name,size,interpretter); + this.compliance = compliance; + } + public FixedFieldPackager(String name,String value, Interpreter interpretter) { + this.interpretter = interpretter; + this.setName(name); + this.setValue(value); + this.size = value.length(); + } + + @Override + public int unpack(byte[] inStream, int offset, Map fields) throws ISOException { + + + int packedSize = interpretter.getPackedLength(size); + if (inStream.length - offset < packedSize) { + throw new ISOException(String.format("Field [%s] at offset [%d]:Expecting %d bytes found %d", getName(),offset,packedSize, inStream.length - offset)); + } + String interprettedvalue = interpretter.uninterpret(inStream, offset, size); + if (getValue() != null) { + if (!getValue().equals(interprettedvalue)) { + throw new ISOException(String.format("Field [%s] at offset [%d]:Expected %s but found %s", getName(),offset,getValue(), interprettedvalue)); + } + } + + fields.put(getName(),interprettedvalue); + value = interprettedvalue; + return offset + packedSize; + + } + + @Override + public byte[] pack(Map fields) throws ISOException { + + if (value== null) {// if the hardcoded value is in the constructor , use it. + value = fields.get(getName()); + + } + else { + fields.put(getName(), value); + } + if (value==null){ + throw new ISOException(String.format("Field [%s]: Unable to pack as field is not set",getName())); + } + if (value.length() <= size) { + if (padLeft){ + ISOUtil.padleft(getValue(), size,(char) padCharacter.byteValue() ); + } + else { + ISOUtil.padright(getValue(), size,(char) padCharacter.byteValue() ); + } + } + else { + throw new ISOException(String.format("Field [%s]:Cannot pack as data has size %d and size needs to be %d",getName(), value.length(),size)); + } + + byte[] packedbyte = new byte[interpretter.getPackedLength(size)]; + interpretter.interpret(getValue(), packedbyte, 0); + return packedbyte; + + } + + @Override + public String getValue() { + return value; + } + + @Override + public void setValue(String value) { + this.value = value; + } + + + + public void setPad(boolean padLeft) { + this.padLeft = padLeft; + this.padright = !padLeft; + } + + public Byte getPadCharacter() { + return padCharacter; + } + + public void setPadCharacter(Byte padCharacter) { + this.padCharacter = padCharacter; + } + + @Override + public String dump(String prefix,Map setfields) { + if (getValue()!=null) + return String.format("%s%n", prefix,getName(),compliance.makeCompliant(getValue())); + return ""; + } + @Override + public byte[] hexDump(String prefix,Map setfields) { + + int numberOfPackedBytes = interpretter.getPackedLength(getValue().length()); + String compliant = compliance.makeCompliant(getValue()); + byte[] temp = new byte[numberOfPackedBytes]; + try { + interpretter.interpret(compliant, temp, 0); + } catch (ISOException e) { + // TODO Auto-generated catch block + return null; + } + return temp; + + + + + } + @Override + public String getParserTree(String prefix) { + + return String.format("%sField [%s] : Fixed [%d] %s%n", prefix,getName(),size, (value==null)?"":": "+value); + } + + + +} diff --git a/modules/fsdmsgx/src/main/java/org/jpos/fsdpackager/IFSDFieldPackager.java b/modules/fsdmsgx/src/main/java/org/jpos/fsdpackager/IFSDFieldPackager.java new file mode 100644 index 0000000000..e2d0ebe41e --- /dev/null +++ b/modules/fsdmsgx/src/main/java/org/jpos/fsdpackager/IFSDFieldPackager.java @@ -0,0 +1,81 @@ +/* + * jPOS Project [http://jpos.org] + * Copyright (C) 2000-2015 Alejandro P. Revilla + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.jpos.fsdpackager; + +import java.util.Map; + +import org.jpos.iso.ISOException; + +public interface IFSDFieldPackager { + + /** + * @param inStream + * the byte array containing data to be parsed and unpacked into + * the {@link FSDMsgX} object. + * @param offset + * The current position where the parser is at. + * @param fields + * A map containing the field name and value. + * + * @return The offset in the instream after unpacking using current field + * packager. + * @throws ISOException + */ + public int unpack(byte[] inStream, int offset, Map fields) throws ISOException; + + /** + * @param setfields + * A map containing the field name and values tha are set up. + * @return The byte array containing data the current fieldpackager packed. + * @throws ISOException + */ + public byte[] pack(Map setfields) throws ISOException; + + public String getValue(); + + public void setValue(String value); + + /** + * @param prefix + * Prepending Text. + * @param setfields + * A map containing the field name as key and text representation + * of the value. + * @return A pretty printed xml string. + */ + public String dump(String prefix, Map setfields); + + /** + * @param prefix + * Prepending decorative text. + * @param setfields + * A map containing the field name as key and text representation + * of the value. + * @return A hexdump of the data stream. + */ + public byte[] hexDump(String prefix, Map setfields); + + /** + * @param prefix + * Prepending decorative text. + * @return A descriptive string of the parsing rule. + */ + public String getParserTree(String prefix); + +} diff --git a/modules/fsdmsgx/src/main/java/org/jpos/fsdpackager/LookAheadPackager.java b/modules/fsdmsgx/src/main/java/org/jpos/fsdpackager/LookAheadPackager.java new file mode 100644 index 0000000000..023ff3e83f --- /dev/null +++ b/modules/fsdmsgx/src/main/java/org/jpos/fsdpackager/LookAheadPackager.java @@ -0,0 +1,182 @@ +/* + * jPOS Project [http://jpos.org] + * Copyright (C) 2000-2015 Alejandro P. Revilla + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.jpos.fsdpackager; + +import java.util.Map; + +import org.jpos.iso.ISOException; + +public class LookAheadPackager extends AFSDFieldPackager { + + private int lookAheadOffset; + private Byte lookUpData; + private AFSDFieldPackager useIfSet; + private AFSDFieldPackager useIfNotSet; + private boolean addLooklookUpValuePresent; + private String[] fieldNamesSet; + + /** + * @param name + * the name of the field + * @param lookAheadOffset + * A positive or negative number to look up a byte. + * @param lookUpData + * Value to lookup at the lookAheadOffset + * @param useIfSet + * If lookUpData was found, the stream to follow + * @param useIfNotSet + * If lookUpData was not found, the stream to follow + * @param fieldNamesSet + * Used to determine if the lookUpData should be set at packing + * time based on fields that are set. + * @param fieldNamesnotSet + * Used to determine if the lookUpData should be set at packing + * time based on fields that are not set. + */ + public LookAheadPackager(String name, int lookAheadOffset, Byte lookUpData, AFSDFieldPackager useIfSet, + AFSDFieldPackager useIfNotSet, String[] fieldNamesSet, String[] fieldNamesnotSet) { + + this.setName(name); + this.lookAheadOffset = lookAheadOffset; + this.lookUpData = lookUpData; + this.useIfSet = useIfSet; + this.useIfNotSet = useIfNotSet; + this.fieldNamesSet = fieldNamesSet; + } + + @Override + public byte[] pack(Map setfields) throws ISOException { + + addLooklookUpValuePresent = true; + for (String fieldName : fieldNamesSet) { + if (setfields.get(fieldName) != null) { + continue; + } + addLooklookUpValuePresent = false; + break; + } + + if (addLooklookUpValuePresent) { + if (useIfSet != null) + return useIfSet.pack(setfields); + } else { + if (useIfNotSet != null) { + return useIfNotSet.pack(setfields); + } + } + + return null; + // TODO Auto-generated method stub + //return super.pack(setfields); + } + + @Override + public int unpack(byte[] inStream, int offset, Map fields) throws ISOException { + + if ((offset + lookAheadOffset) < inStream.length) { + + if (inStream[offset + lookAheadOffset] == lookUpData.byteValue()) { + if (useIfSet != null) { + offset = useIfSet.unpack(inStream, offset, fields); + fields.put(useIfSet.getName(), useIfSet.getValue()); + } + } else { + if (useIfNotSet != null) { + offset = useIfNotSet.unpack(inStream, offset, fields); + fields.put(useIfNotSet.getName(), useIfNotSet.getValue()); + + } + } + } + return offset; + + } + + @Override + public String dump(String prefix, Map setfields) { + addLooklookUpValuePresent = true; + for (String fieldName : fieldNamesSet) { + if (setfields.get(fieldName) != null) { + continue; + } + addLooklookUpValuePresent = false; + break; + } + + if (addLooklookUpValuePresent) { + if (useIfSet != null) + return useIfSet.dump(prefix, setfields); + } else { + if (useIfNotSet != null) { + return useIfNotSet.dump(prefix, setfields); + } + } + return ""; + + } + + @Override + public byte[] hexDump(String prefix, Map setfields) { + + addLooklookUpValuePresent = true; + for (String fieldName : fieldNamesSet) { + if (setfields.get(fieldName) != null) { + continue; + } + addLooklookUpValuePresent = false; + break; + } + + if (addLooklookUpValuePresent) { + if (useIfSet != null) + return useIfSet.hexDump(prefix, setfields); + } else { + if (useIfNotSet != null) { + return useIfNotSet.hexDump(prefix, setfields); + } + } + return null; + + } + + @Override + public String getParserTree(String prefix) { + + String setFieldsNames=""; + for (String name:fieldNamesSet){ + + setFieldsNames+=(name+","); + + } + String ifset = useIfSet!=null?useIfSet.getParserTree("\t\t\t\t\t"):"\t\t\t\t\t[Not Set]"+System.lineSeparator(); + String ifnotset=useIfNotSet!=null?useIfNotSet.getParserTree("\t\t\t\t\t"):"\t\t\t\t\t[Not Set]"+System.lineSeparator(); + String s = String.format("%sField [%s] : [LookAhead]%n" + + "\t\t\toffset[%d] find[0x%X]%n" + + "\t\t\t\t[if found]%n" + + "%s" + + "\t\t\t\t[if not found]%n" + + "%s" + + "\t\t\tCheck Field[%s]%n", prefix,getName(),lookAheadOffset,lookUpData.byteValue(),ifset,ifnotset,setFieldsNames); + // TODO Auto-generated method stub + return s; + } + + + +} diff --git a/modules/fsdmsgx/src/main/java/org/jpos/fsdpackager/OptionalPackager.java b/modules/fsdmsgx/src/main/java/org/jpos/fsdpackager/OptionalPackager.java new file mode 100644 index 0000000000..a271f8e30d --- /dev/null +++ b/modules/fsdmsgx/src/main/java/org/jpos/fsdpackager/OptionalPackager.java @@ -0,0 +1,82 @@ +/* + * jPOS Project [http://jpos.org] + * Copyright (C) 2000-2015 Alejandro P. Revilla + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.jpos.fsdpackager; + +import java.util.Map; + +import org.jpos.iso.ISOException; + +public class OptionalPackager extends AFSDFieldPackager { + + private AFSDFieldPackager fieldPackager; + + public OptionalPackager(String name,AFSDFieldPackager fieldPackager){ + + this.fieldPackager = fieldPackager; + setName(name); + + } + + @Override + public byte[] pack(Map setfields) throws ISOException { + + try { + return fieldPackager.pack(setfields); + + } catch (Exception e) { + ;// If optional was absent, pack would have thrown an exception as field was not set + } + return null; + } + + @Override + public int unpack(byte[] inStream, int offset, Map fields) throws ISOException { + try{ + return fieldPackager.unpack(inStream, offset, fields); + } + catch (Exception ex){ + ;//Do nothing, means optional field not present + } + return offset; // return original offset passed in + } + + @Override + public String getParserTree(String prefix) { + // TODO Auto-generated method stub + return String.format("%sField [%s] : [OPTIONAL]%n",prefix,getName()) +fieldPackager.getParserTree(prefix+"\t"); + + } + + @Override + public String dump(String prefix, Map setfields) { + + try { + return fieldPackager.dump(prefix, setfields); + } catch (Exception e) { + // TODO: handle exception + } + return ""; + } + + + + + + +} diff --git a/modules/fsdmsgx/src/main/java/org/jpos/fsdpackager/VariableFieldPackager.java b/modules/fsdmsgx/src/main/java/org/jpos/fsdpackager/VariableFieldPackager.java new file mode 100644 index 0000000000..2fe0131edf --- /dev/null +++ b/modules/fsdmsgx/src/main/java/org/jpos/fsdpackager/VariableFieldPackager.java @@ -0,0 +1,180 @@ +/* + * jPOS Project [http://jpos.org] + * Copyright (C) 2000-2015 Alejandro P. Revilla + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.jpos.fsdpackager; + +import java.util.Map; + +import org.jpos.fsdpackager.compliance.APCICompliance; +import org.jpos.fsdpackager.compliance.NoCompliance; +import org.jpos.iso.AsciiInterpreter; +import org.jpos.iso.ISOException; +import org.jpos.iso.Interpreter; + +public class VariableFieldPackager extends AFSDFieldPackager { + + String value; + Byte delimiter; + Interpreter interpreter = AsciiInterpreter.INSTANCE; + private int maxSize = Integer.MAX_VALUE; + int size; + boolean mandatory = false; + private APCICompliance compliance = new NoCompliance(); + + @Override + public int unpack(byte[] inStream, int offset, Map fields) throws ISOException { + + boolean delimiterFound = false; + int i = offset; + int lengthTotraverse; + if (maxSize <= inStream.length - offset) // length-offset = remaining + // bytes + lengthTotraverse = maxSize + offset + 1;// to incluse th delimiter + else + lengthTotraverse = inStream.length; + while (i < lengthTotraverse) { // there is no point traversing to the + // end, if we can we should traverse to + // the maxsize + if (inStream[i] == delimiter.byteValue()) { + delimiterFound = true; + break; + } + + i++; + } + if (delimiterFound || i == inStream.length) { + + byte[] dest = new byte[i - offset]; + if ((i - offset) == 0) { + // Means there is no data and its terminated by delimiter + value = ""; + } else if ((i - offset) <= maxSize) { + System.arraycopy(inStream, offset, dest, 0, i - offset); + value = interpreter.uninterpret(dest, 0, i - offset); + + } else + throw new ISOException( + String.format("Field size [%d] is greater than max size [%d] of field ", i - offset, maxSize)); + + } else { + throw new ISOException(String.format("Field [%s]: Delimiter %x not present after max size %d", getName(), + delimiter.byteValue(), maxSize)); + } + setValue(value); + return i - offset + 1; + } + + @Override + public byte[] pack(Map fields) throws ISOException { + + if (value == null || value.equals("")) { + // if field is not set, make sure to send the delimiter to indicate + // its presence. + return new byte[] { delimiter.byteValue() }; + } + if (value.length() <= maxSize) { + byte[] b = new byte[interpreter.getPackedLength(value.length() + 1)]; + interpreter.interpret(value, b, 0); + b[b.length - 1] = delimiter.byteValue(); + + return b; + } + throw new ISOException(String.format("Size [%d] is greater than maxSize[%d] ", value.length(), maxSize)); + } + + public VariableFieldPackager(String name, int maxSize, Byte delimiter, Interpreter interpretter) { + + this.maxSize = maxSize; + this.interpreter = interpretter; + this.delimiter = delimiter; + this.setName(name); + } + + public VariableFieldPackager(String name, int maxSize, Byte delimiter, Interpreter interpretter, + APCICompliance compliance) { + this(name, maxSize, delimiter, interpretter); + this.compliance = compliance; + } + + public VariableFieldPackager(String name, Byte delimiter, Interpreter interpretter) { + + this.interpreter = interpretter; + this.delimiter = delimiter; + this.setName(name); + } + + public VariableFieldPackager(String name, Byte delimiter, Interpreter interpretter, APCICompliance compliance) { + + this.interpreter = interpretter; + this.delimiter = delimiter; + this.setName(name); + this.compliance = compliance; + } + + public VariableFieldPackager(String name, int maxSize, Byte delimiter, Interpreter interpretter, + boolean mandatory) { + + this(name, maxSize, delimiter, interpretter); + this.mandatory = mandatory; + } + + @Override + public String getValue() { + // TODO Auto-generated method stub + return value; + } + + @Override + public void setValue(String value) { + this.value = value; + // TODO Auto-generated method stub + + } + + @Override + public String dump(String prefix, Map setfields) { + if (getValue()!=null) + return String.format("%s%n", prefix, getName(), + compliance.makeCompliant(getValue())); + return ""; + } + + @Override + public byte[] hexDump(String prefix, Map setfields) { + + int numberOfPackedBytes = interpreter.getPackedLength(getValue().length()); + String compliant = compliance.makeCompliant(getValue()); + byte[] temp = new byte[numberOfPackedBytes]; + try { + interpreter.interpret(compliant, temp, 0); + } catch (ISOException e) { + // TODO Auto-generated catch block + return null; + } + return temp; + + } + + @Override + public String getParserTree(String prefix) { + + return String.format("%sField [%s] : VAR[0..%d] delimiter[0x%X] or EOM%n %s", prefix, getName(),maxSize, delimiter.byteValue(), getValue()==null?"":": "+getValue()); + + } + +} diff --git a/modules/fsdmsgx/src/main/java/org/jpos/fsdpackager/compliance/APCICompliance.java b/modules/fsdmsgx/src/main/java/org/jpos/fsdpackager/compliance/APCICompliance.java new file mode 100644 index 0000000000..98ac78e00b --- /dev/null +++ b/modules/fsdmsgx/src/main/java/org/jpos/fsdpackager/compliance/APCICompliance.java @@ -0,0 +1,28 @@ +/* + * jPOS Project [http://jpos.org] + * Copyright (C) 2000-2015 Alejandro P. Revilla + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.jpos.fsdpackager.compliance; + +public class APCICompliance implements IPCICompliance { + + public String makeCompliant(String noncompliant) { + // TODO Auto-generated method stub + return noncompliant; + } + +} diff --git a/modules/fsdmsgx/src/main/java/org/jpos/fsdpackager/compliance/IPCICompliance.java b/modules/fsdmsgx/src/main/java/org/jpos/fsdpackager/compliance/IPCICompliance.java new file mode 100644 index 0000000000..252207737c --- /dev/null +++ b/modules/fsdmsgx/src/main/java/org/jpos/fsdpackager/compliance/IPCICompliance.java @@ -0,0 +1,27 @@ +/* + * jPOS Project [http://jpos.org] + * Copyright (C) 2000-2015 Alejandro P. Revilla + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.jpos.fsdpackager.compliance; + +public interface IPCICompliance { + + public String makeCompliant(String noncompliant); + + + +} diff --git a/modules/fsdmsgx/src/main/java/org/jpos/fsdpackager/compliance/NoCompliance.java b/modules/fsdmsgx/src/main/java/org/jpos/fsdpackager/compliance/NoCompliance.java new file mode 100644 index 0000000000..fe20c4a434 --- /dev/null +++ b/modules/fsdmsgx/src/main/java/org/jpos/fsdpackager/compliance/NoCompliance.java @@ -0,0 +1,32 @@ +/* + * jPOS Project [http://jpos.org] + * Copyright (C) 2000-2015 Alejandro P. Revilla + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.jpos.fsdpackager.compliance; + +import org.jpos.iso.ISOException; +import org.jpos.iso.ISOUtil; + +public class NoCompliance extends APCICompliance { + + @Override + public String makeCompliant(String noncompliant) { + + return super.makeCompliant(noncompliant); + } + +} diff --git a/modules/fsdmsgx/src/main/java/org/jpos/fsdpackager/compliance/TrackDataCompliance.java b/modules/fsdmsgx/src/main/java/org/jpos/fsdpackager/compliance/TrackDataCompliance.java new file mode 100644 index 0000000000..e4bdaec442 --- /dev/null +++ b/modules/fsdmsgx/src/main/java/org/jpos/fsdpackager/compliance/TrackDataCompliance.java @@ -0,0 +1,32 @@ +/* + * jPOS Project [http://jpos.org] + * Copyright (C) 2000-2015 Alejandro P. Revilla + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.jpos.fsdpackager.compliance; + +import org.jpos.iso.ISOUtil; + +public class TrackDataCompliance extends APCICompliance { + + @Override + public String makeCompliant(String noncompliant) { + + return ISOUtil.protect(noncompliant); + } + + +} diff --git a/modules/fsdmsgx/src/main/java/org/jpos/fsdpackager/compliance/WipeCompliance.java b/modules/fsdmsgx/src/main/java/org/jpos/fsdpackager/compliance/WipeCompliance.java new file mode 100644 index 0000000000..65a4b8d345 --- /dev/null +++ b/modules/fsdmsgx/src/main/java/org/jpos/fsdpackager/compliance/WipeCompliance.java @@ -0,0 +1,38 @@ +/* + * jPOS Project [http://jpos.org] + * Copyright (C) 2000-2015 Alejandro P. Revilla + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.jpos.fsdpackager.compliance; + +import org.jpos.iso.ISOException; +import org.jpos.iso.ISOUtil; + +public class WipeCompliance extends APCICompliance { + + @Override + public String makeCompliant(String noncompliant) { + + try { + return (ISOUtil.padleft("", noncompliant.length(), '*')); + } catch (ISOException e) { + + return "BAD DATA"; + } + + } + +} diff --git a/modules/fsdmsgx/src/main/java/org/jpos/iso/FSDISOMsgX.java b/modules/fsdmsgx/src/main/java/org/jpos/iso/FSDISOMsgX.java new file mode 100644 index 0000000000..f474287cb6 --- /dev/null +++ b/modules/fsdmsgx/src/main/java/org/jpos/iso/FSDISOMsgX.java @@ -0,0 +1,105 @@ +/* + * jPOS Project [http://jpos.org] + * Copyright (C) 2000-2015 Alejandro P. Revilla + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.jpos.iso; + +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.io.PrintStream; +import java.util.Iterator; +import java.util.Map; + +import org.jdom.JDOMException; +import org.jpos.fsdpackager.FSDMsgX; +import org.jpos.iso.ISOException; +import org.jpos.iso.ISOMsg; +import org.jpos.util.FSDMsg; + +public class FSDISOMsgX extends ISOMsg { + FSDMsgX fsd; + public FSDISOMsgX () { + super(); + } + public FSDISOMsgX (FSDMsgX fsd) { + super(); + this.fsd = fsd; + } + public String getMTI() { + return getString(0); + } + public byte[] pack() throws ISOException { + try { + return fsd.pack(); + } catch (Exception e) { + throw new ISOException (e); + } + } + public int unpack(byte[] b) throws ISOException { + try { + return fsd.unpack (b); + + } catch (Exception e) { + throw new ISOException (e); + } + } + public void unpack (InputStream in) throws IOException, ISOException { + throw new UnsupportedOperationException(); + } + + public FSDMsgX getFSDMsg() { + return fsd; + } + public String getString (int fldno) { + return fsd.get (Integer.toString(fldno)); + } + public String getString (String fld) { + return fsd.get (fld); + } + public boolean hasField (int fldno) { + return getString(fldno) != null; + } + public boolean hasField (String fld) { + return getString(fld) != null; + } + public void dump (PrintStream p, String indent) { + if (fsd != null) + p.println( fsd.dump (indent)); + } + public void writeExternal (ObjectOutput out) throws IOException { + throw new UnsupportedOperationException(); + } + public void readExternal (ObjectInput in) + throws IOException, ClassNotFoundException + { + throw new UnsupportedOperationException(); + + } + public void setResponseMTI() { + try { + super.setResponseMTI(); + } catch (ISOException ignored) { } + } + public void set (String name, String value) { + if (value != null) + this.fsd.set (name, value); + } + private static final long serialVersionUID = 1L; +} + diff --git a/modules/fsdmsgx/src/test/java/org/jpos/fsdpackager/BranchFieldPackagerTest.java b/modules/fsdmsgx/src/test/java/org/jpos/fsdpackager/BranchFieldPackagerTest.java new file mode 100644 index 0000000000..a9f85704f3 --- /dev/null +++ b/modules/fsdmsgx/src/test/java/org/jpos/fsdpackager/BranchFieldPackagerTest.java @@ -0,0 +1,311 @@ +/* + * jPOS Project [http://jpos.org] + * Copyright (C) 2000-2015 Alejandro P. Revilla + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.jpos.fsdpackager; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; + +import java.util.HashMap; +import java.util.Map; + +import org.jpos.iso.AsciiInterpreter; +import org.jpos.iso.ISOException; +import org.jpos.iso.LiteralInterpreter; +import org.junit.Test; + +public class BranchFieldPackagerTest { + + + @Test + public void unpackTest06() throws ISOException{ + + AFSDFieldPackager f1 = new FixedFieldPackager("F1", 5, AsciiInterpreter.INSTANCE); + AFSDFieldPackager f2 = new FixedFieldPackager("F2", 2, AsciiInterpreter.INSTANCE); + + + FSDMsgX innerFSDCase01 = new FSDMsgX("inner-1"); + AFSDFieldPackager f7 = new FixedFieldPackager("F7", 3, AsciiInterpreter.INSTANCE); + AFSDFieldPackager f6 = new FixedFieldPackager("F6", 3, AsciiInterpreter.INSTANCE); + + innerFSDCase01.add("F7",f7); + innerFSDCase01.add("F6",f6); + FSDMsgX innerFSDCase02 = new FSDMsgX("inner-1"); + + AFSDFieldPackager f8 = new FixedFieldPackager("F8", 4, AsciiInterpreter.INSTANCE); + AFSDFieldPackager f9 = new FixedFieldPackager("F9", 4, AsciiInterpreter.INSTANCE); + + innerFSDCase02.add("F8",f8); + innerFSDCase02.add("F9",f9); + Map caseMap = new HashMap(); + caseMap.put("01", innerFSDCase01); + caseMap.put("02", innerFSDCase02); + AFSDFieldPackager f3 = new BranchFieldPackager("F3", "F2", caseMap, null); + + FSDMsgX msg = new FSDMsgX("Test"); + msg.add("F1", f1); + msg.add("F2", f2); + msg.add("F3", f3); + + msg.unpack("ABCDE0244445555".getBytes()); + System.out.println(msg.dump("")); + assertEquals("ABCDE", msg.get("F1")); + assertEquals("02", msg.get("F2")); + + assertEquals("4444", msg.get("F8")); + assertEquals("5555", msg.get("F9")); + + + + } + @Test + public void packTest03() throws ISOException{ + + AFSDFieldPackager f1 = new FixedFieldPackager("F1", 5, AsciiInterpreter.INSTANCE); + AFSDFieldPackager f2 = new FixedFieldPackager("F2", 2, AsciiInterpreter.INSTANCE); + + AFSDFieldPackager case02 = new FixedFieldPackager("F5", 4, AsciiInterpreter.INSTANCE); + + FSDMsgX innerFSDCase01 = new FSDMsgX("Test"); + AFSDFieldPackager f4 = new FixedFieldPackager("F4", 3, AsciiInterpreter.INSTANCE); + + innerFSDCase01.add("Inner",f4); + Map caseMap = new HashMap(); + caseMap.put("01", innerFSDCase01); + caseMap.put("02", case02); + AFSDFieldPackager f3 = new BranchFieldPackager("F3", "F2", caseMap, null); + + FSDMsgX msg = new FSDMsgX("Test"); + msg.add("F1", f1); + msg.add("F2", f2); + msg.add("F3", f3); + + msg.set("F1", "ABCDE"); + msg.set("F2", "01"); + msg.set("F4", "333"); + msg.set("F5", "4444"); + + + byte[] outStream = msg.pack(); + + assertArrayEquals("ABCDE01333".getBytes(), outStream); + + + + } + + + @Test + public void packTest04() throws ISOException{ + + AFSDFieldPackager f1 = new FixedFieldPackager("F1", 5, AsciiInterpreter.INSTANCE); + AFSDFieldPackager f2 = new FixedFieldPackager("F2", 2, AsciiInterpreter.INSTANCE); + + AFSDFieldPackager case01 = new FixedFieldPackager("F4", 3, AsciiInterpreter.INSTANCE); + AFSDFieldPackager case02 = new FixedFieldPackager("F5", 4, AsciiInterpreter.INSTANCE); + + Map caseMap = new HashMap(); + caseMap.put("01", case01); + caseMap.put("02", case02); + AFSDFieldPackager f3 = new BranchFieldPackager("F3", "F2", caseMap, null); + + FSDMsgX msg = new FSDMsgX("Test"); + msg.add("F1", f1); + msg.add("F2", f2); + msg.add("F3", f3); + + msg.set("F1", "ABCDE"); + msg.set("F2", "03"); + msg.set("F4", "333"); + msg.set("F5", "4444"); + + + byte[] outStream = msg.pack(); + + assertArrayEquals("ABCDE03".getBytes(), outStream); + //System.out.println(ISOUtil.hexdump(outStream)); + + + + } + + @Test + public void packTest05() throws ISOException{ + + AFSDFieldPackager f1 = new FixedFieldPackager("F1", 5, AsciiInterpreter.INSTANCE); + AFSDFieldPackager f2 = new FixedFieldPackager("F2", 2, AsciiInterpreter.INSTANCE); + + AFSDFieldPackager case01 = new FixedFieldPackager("F4", 3, AsciiInterpreter.INSTANCE); + AFSDFieldPackager case02 = new FixedFieldPackager("F5", 4, AsciiInterpreter.INSTANCE); + + Map caseMap = new HashMap(); + caseMap.put("01", case01); + caseMap.put("02", case02); + AFSDFieldPackager f3 = new BranchFieldPackager("F3", "F2", caseMap, null); + + FSDMsgX msg = new FSDMsgX("Test"); + msg.add("F1", f1); + msg.add("F2", f2); + msg.add("F3", f3); + + msg.set("F1", "ABCDE"); + msg.set("F2", "02"); + msg.set("F4", "333"); + msg.set("F5", "4444"); + + + byte[] outStream = msg.pack(); + System.out.println(msg.getParserTree("")); + + assertArrayEquals("ABCDE024444".getBytes(), outStream); + //System.out.println(ISOUtil.hexdump(outStream)); + + + + } + + @Test + public void packTest08() throws ISOException{ + + AFSDFieldPackager f1 = new FixedFieldPackager("F1", 5, AsciiInterpreter.INSTANCE); + AFSDFieldPackager f2 = new FixedFieldPackager("F2", 2, AsciiInterpreter.INSTANCE); + + AFSDFieldPackager case01 = new FixedFieldPackager("F4", 3, AsciiInterpreter.INSTANCE); + AFSDFieldPackager case02 = new FixedFieldPackager("F5", 4, AsciiInterpreter.INSTANCE); + + Map caseMap = new HashMap(); + caseMap.put("01", case01); + caseMap.put("02", case02); + AFSDFieldPackager f3 = new BranchFieldPackager("F3", "F2", caseMap, null); + AFSDFieldPackager f6 = new FixedFieldPackager("F6", 1, LiteralInterpreter.INSTANCE); + + FSDMsgX msg = new FSDMsgX("Test"); + msg.add("F1", f1); + msg.add("F2", f2); + msg.add("F3", f3); + msg.add("F6", f6); + + msg.set("F1", "ABCDE"); + msg.set("F2", "01"); + msg.set("F4", "333"); + msg.set("F5", "4444"); + msg.set("F6", String.valueOf((char)0x02)); + + + byte[] outStream = msg.pack(); + + assertArrayEquals(("ABCDE01333"+(char)0x02).getBytes(), outStream); + //System.out.println(ISOUtil.hexdump(outStream)); + + } + + @Test + public void packTest07() throws ISOException{ + + AFSDFieldPackager f1 = new FixedFieldPackager("F1", 5, AsciiInterpreter.INSTANCE); + AFSDFieldPackager f2 = new FixedFieldPackager("F2", 2, AsciiInterpreter.INSTANCE); + + AFSDFieldPackager case01 = new FixedFieldPackager("F4", 3, AsciiInterpreter.INSTANCE); + AFSDFieldPackager case02 = new FixedFieldPackager("F5", 4, AsciiInterpreter.INSTANCE); + + Map caseMap = new HashMap(); + caseMap.put("01", case01); + caseMap.put("02", case02); + AFSDFieldPackager f3 = new BranchFieldPackager("F3", "F2", caseMap, null); + AFSDFieldPackager f6 = new FixedFieldPackager("F6", 1, LiteralInterpreter.INSTANCE); + + FSDMsgX msg = new FSDMsgX("Test"); + msg.add("F1", f1); + msg.add("F2", f2); + msg.add("F3", f3); + // F6 is not added to the message. + + msg.set("F1", "ABCDE"); + msg.set("F2", "01"); + msg.set("F4", "333"); + msg.set("F5", "4444"); + msg.set("F6", String.valueOf((char)0x02)); + // But F6 is set, should have no impact on the output. + + byte[] outStream = msg.pack(); + + assertArrayEquals("ABCDE01333".getBytes(), outStream); + //System.out.println(ISOUtil.hexdump(outStream)); + + } + + @Test + public void packTest06() throws ISOException{ + + AFSDFieldPackager f1 = new FixedFieldPackager("F1", 5, AsciiInterpreter.INSTANCE); + AFSDFieldPackager f2 = new FixedFieldPackager("F2", 2, AsciiInterpreter.INSTANCE); + + AFSDFieldPackager case01 = new FixedFieldPackager("F4", 3, AsciiInterpreter.INSTANCE); + AFSDFieldPackager case02 = new FixedFieldPackager("F5", 4, AsciiInterpreter.INSTANCE); + + Map caseMap = new HashMap(); + caseMap.put("01", case01); + caseMap.put("02", case02); + AFSDFieldPackager f3 = new BranchFieldPackager("F3", "F2", caseMap, null); + + FSDMsgX msg = new FSDMsgX("Test"); + msg.add("F1", f1); + msg.add("F2", f2); + msg.add("F3", f3); + + msg.set("F1", "ABCDE"); + msg.set("F2", "01"); + msg.set("F4", "333"); + msg.set("F5", "4444"); + + + byte[] outStream = msg.pack(); + + assertArrayEquals("ABCDE01333".getBytes(), outStream); + //System.out.println(ISOUtil.hexdump(outStream)); + + } + + @Test + public void unpacktest07() throws ISOException{ + AFSDFieldPackager f1 = new FixedFieldPackager("F1", 5, AsciiInterpreter.INSTANCE); + AFSDFieldPackager f2 = new FixedFieldPackager("F2", 2, AsciiInterpreter.INSTANCE); + + AFSDFieldPackager case01 = new FixedFieldPackager("F4", 3, AsciiInterpreter.INSTANCE); + AFSDFieldPackager case02 = new FixedFieldPackager("F5", 4, AsciiInterpreter.INSTANCE); + + Map caseMap = new HashMap(); + caseMap.put("01", case01); + caseMap.put("02", case02); + AFSDFieldPackager f3 = new BranchFieldPackager("F3", "F2", caseMap, null); + + FSDMsgX msg = new FSDMsgX("Test"); + msg.add("F1", f1); + msg.add("F2", f2); + msg.add("F3", f3); + + String raw = "12345" + "02" + "0000"; + msg.unpack(raw.getBytes()); + + //System.out.println(msg.dump("")); + + } + + + +} diff --git a/modules/fsdmsgx/src/test/java/org/jpos/fsdpackager/FixedFieldPackagerTest.java b/modules/fsdmsgx/src/test/java/org/jpos/fsdpackager/FixedFieldPackagerTest.java new file mode 100644 index 0000000000..d7f6597c3a --- /dev/null +++ b/modules/fsdmsgx/src/test/java/org/jpos/fsdpackager/FixedFieldPackagerTest.java @@ -0,0 +1,235 @@ +/* + * jPOS Project [http://jpos.org] + * Copyright (C) 2000-2015 Alejandro P. Revilla + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.jpos.fsdpackager; + +import static org.junit.Assert.*; + +import java.util.HashMap; +import java.util.Map; + +import org.jpos.fsdpackager.compliance.TrackDataCompliance; +import org.jpos.iso.AsciiInterpreter; +import org.jpos.iso.BCDInterpreter; +import org.jpos.iso.EbcdicInterpreter; +import org.jpos.iso.ISOException; +import org.jpos.iso.ISOUtil; +import org.jpos.iso.LiteralInterpreter; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +public class FixedFieldPackagerTest { + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Test + public void unpackTest01() throws ISOException { + int size = 5; + FixedFieldPackager p = new FixedFieldPackager("F1", size, AsciiInterpreter.INSTANCE); + FSDMsgX msg = new FSDMsgX("Test"); + ; + msg.add("F1", p); + + String s = "12ABCDEFH"; + int offset = msg.unpack(s.getBytes()); + assertEquals(size, offset); + assertEquals("12ABC", msg.get("F1")); + System.out.println(msg.get("F1")); + System.out.println(msg.dump("")); + + } + + @Test + public void unpackTest02() throws ISOException { + + // byte[] f = ISOUtil.str2bcd("12345", false); + // String s = ISOUtil.bcd2str(f, 0, 5, false); + int size = 5; + FixedFieldPackager p = new FixedFieldPackager("F1", size, BCDInterpreter.RIGHT_PADDED); + FSDMsgX msg = new FSDMsgX("Test"); + ; + msg.add("F1", p); + + byte[] b = { 0x12, 0x34, 0x56, 0x78 }; + int offset = msg.unpack(b); + assertEquals(BCDInterpreter.RIGHT_PADDED.getPackedLength(5), offset); + assertEquals("12345", msg.get("F1")); + + } + + @Test + public void unpackTest03() throws ISOException { + thrown.expect(ISOException.class); + thrown.expectMessage("Field [F1] at offset [0]:Expecting 5 bytes found 4"); + + int size = 5; + FixedFieldPackager p = new FixedFieldPackager("F1", size, AsciiInterpreter.INSTANCE); + String s = "12AB"; + FSDMsgX msg = new FSDMsgX("Test"); + ; + msg.add("F1", p); + + int offset = msg.unpack(s.getBytes()); + assertEquals(size + 1, offset); + assertEquals("12ABC", msg.get("F1")); + + } + + @Test + public void unpackTest04() throws ISOException { + + FixedFieldPackager p = new FixedFieldPackager("F1", "12345", AsciiInterpreter.INSTANCE); + String s = "12345"; + FSDMsgX msg = new FSDMsgX("Test"); + ; + msg.add("F1", p); + + int offset = msg.unpack(s.getBytes()); + assertEquals(5, offset); + assertEquals("12345", msg.get("F1")); + + } + + @Test + public void unpackTest05() throws ISOException { + + thrown.expect(ISOException.class); + thrown.expectMessage("Expected 12345 but found 12346"); + FixedFieldPackager p = new FixedFieldPackager("F1", "12345", AsciiInterpreter.INSTANCE); + String s = "12346"; + FSDMsgX msg = new FSDMsgX("Test"); + ; + msg.add("F1", p); + + int offset = msg.unpack(s.getBytes()); + assertEquals(5 + 1, offset); + assertEquals("12345", msg.get("F1")); + + } + + @Test + public void unpackTest06() throws ISOException { + + thrown.expect(ISOException.class); + thrown.expectMessage("Expecting 5 bytes found 3"); + + FixedFieldPackager p = new FixedFieldPackager("F1", "12345", AsciiInterpreter.INSTANCE); + String s = "ABC"; + FSDMsgX msg = new FSDMsgX("Test"); + ; + msg.add("F1", p); + + int offset = msg.unpack(s.getBytes()); + assertEquals(5 + 1, offset); + assertEquals("12345", msg.get("F1")); + + } + + @Test + public void packTest01() throws ISOException { + thrown.expect(ISOException.class); + thrown.expectMessage("Cannot pack as data has size 7 and size needs to be 5"); + + FixedFieldPackager p = new FixedFieldPackager("F1", 5, AsciiInterpreter.INSTANCE); + String s = "ABC1234"; + FSDMsgX msg = new FSDMsgX("Test"); + ; + msg.add("F1", p); + msg.set("F1", s); + byte[] b = msg.pack(); + assertEquals(null, b); + + } + + @Test + public void packTest02() throws ISOException { + + FixedFieldPackager p = new FixedFieldPackager("F1", 5, AsciiInterpreter.INSTANCE); + String s = "ABC12"; + FSDMsgX msg = new FSDMsgX("Test"); + ; + msg.add("F1", p); + msg.set("F1", s); + byte[] stream = msg.pack(); + assertArrayEquals("ABC12".getBytes(), stream); + + } + + @Test + public void packTest03() throws ISOException { + + int size = 5; + FixedFieldPackager p = new FixedFieldPackager("F1", size, BCDInterpreter.RIGHT_PADDED); + + FSDMsgX msg = new FSDMsgX("Test"); + ; + msg.add("F1", p); + msg.set("F1", "12345"); + + byte[] b = { 0x12, 0x34, 0x50 }; + byte[] stream = msg.pack(); + assertArrayEquals(b, stream); + + } + + @Test + public void packTest09() throws ISOException { + + int size = 16; + FixedFieldPackager p = new FixedFieldPackager("F1", size, AsciiInterpreter.INSTANCE, new TrackDataCompliance()); + FSDMsgX msg = new FSDMsgX("Test"); + ; + msg.add("F1", p); + + String s = "1234567890123456"; + + msg.set("F1", s); + + byte[] b = msg.pack(); + System.out.println(ISOUtil.hexdump(b)); + System.out.println(msg.dump("")); + System.out.println(msg.hexDump("")); + System.out.println(msg.dump("")); + + } + + @Test + public void packTest10() throws ISOException { + + int size = 16; + FixedFieldPackager p = new FixedFieldPackager("F1", size, EbcdicInterpreter.INSTANCE, + new TrackDataCompliance()); + FSDMsgX msg = new FSDMsgX("Test"); + ; + msg.add("F1", p); + + String s = "1234567890123456"; + + msg.set("F1", s); + + byte[] b = msg.pack(); + System.out.println(ISOUtil.hexdump(b)); + System.out.println(msg.dump("")); + System.out.println(msg.hexDump("")); + System.out.println(msg.dump("")); + + } + +} diff --git a/modules/fsdmsgx/src/test/java/org/jpos/fsdpackager/LookAheadPackagerTest.java b/modules/fsdmsgx/src/test/java/org/jpos/fsdpackager/LookAheadPackagerTest.java new file mode 100644 index 0000000000..82e64a32f0 --- /dev/null +++ b/modules/fsdmsgx/src/test/java/org/jpos/fsdpackager/LookAheadPackagerTest.java @@ -0,0 +1,195 @@ +/* + * jPOS Project [http://jpos.org] + * Copyright (C) 2000-2015 Alejandro P. Revilla + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.jpos.fsdpackager; + +import org.jpos.iso.AsciiInterpreter; +import org.jpos.iso.ISOException; +import org.junit.Test; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; + +public class LookAheadPackagerTest { + + /** + * Lookahead in the stream to see if a certain byte is present, if present + * start parsing the stream based on the set lookup value. + * + * @throws ISOException + */ + @Test + + public void unpacktest01() throws ISOException { + + String s = "ABCD1234XYZ"; + FSDMsgX ifSet = new FSDMsgX("ifSet"); + AFSDFieldPackager f0_a = new FixedFieldPackager("F0", new String(new byte[] { (byte) ';' }), + AsciiInterpreter.INSTANCE); + AFSDFieldPackager f1_a = new FixedFieldPackager("F1", 4, AsciiInterpreter.INSTANCE); + AFSDFieldPackager f2_a = new FixedFieldPackager("F2", 4, AsciiInterpreter.INSTANCE); + + ifSet.add("F1", f1_a); + ifSet.add("F2", f2_a); + ifSet.add("F0", f0_a); + + FSDMsgX ifNotSet = new FSDMsgX("ifnotSet"); + AFSDFieldPackager f1_b = new FixedFieldPackager("F1", 8, AsciiInterpreter.INSTANCE); + ifNotSet.add("F1", f1_b); + + AFSDFieldPackager f3 = new FixedFieldPackager("F3", 3, AsciiInterpreter.INSTANCE); + + FSDMsgX main = new FSDMsgX("main"); + String[] setFields = { "F0" }; + AFSDFieldPackager look = new LookAheadPackager("LA", 8, Byte.valueOf((byte) ';'), ifSet, ifNotSet, setFields, + null); + main.add("LA", look); + main.add("F3", f3); + System.out.println(main.getParserTree("")); + + main.unpack(s.getBytes()); +// assertEquals("ABCD", main.get("F1")); +// assertEquals("1234", main.get("F2")); +// assertEquals(";", main.get("F0")); +// assertEquals("XYZ", main.get("F3")); + System.out.println(main.dump("")); + System.out.println(main.hexDump("")); + + System.out.println(main.getParserTree("")); + + } + + /** + * Lookahead in the stream to see if a certain byte is present, since its not present, choose the ifnotset path + * @throws ISOException + */ + + @Test + + public void unpacktest02() throws ISOException { + + String s = "ABCD1234XYZ"; + + FSDMsgX ifSet = new FSDMsgX("ifSet"); + AFSDFieldPackager f0_a = new FixedFieldPackager("F0", new String(new byte[] { (byte) ';' }), + AsciiInterpreter.INSTANCE); + AFSDFieldPackager f1_a = new FixedFieldPackager("F1", 4, AsciiInterpreter.INSTANCE); + AFSDFieldPackager f2_a = new FixedFieldPackager("F2", 4, AsciiInterpreter.INSTANCE); + + ifSet.add("F1", f1_a); + ifSet.add("F2", f2_a); + ifSet.add("F0", f0_a); + + FSDMsgX ifNotSet = new FSDMsgX("ifnotSet"); + AFSDFieldPackager f1_b = new FixedFieldPackager("F1", 8, AsciiInterpreter.INSTANCE); + ifNotSet.add("F1", f1_b); + + AFSDFieldPackager f3 = new FixedFieldPackager("F3", 3, AsciiInterpreter.INSTANCE); + + FSDMsgX main = new FSDMsgX("main"); + String[] setFields = { "F0" }; + AFSDFieldPackager look = new LookAheadPackager("LA", 8, Byte.valueOf((byte) ';'), ifSet, ifNotSet, setFields, + null); + main.add("LA", look); + main.add("F3", f3); + main.unpack(s.getBytes()); + assertEquals("ABCD1234", main.get("F1")); + assertEquals("XYZ", main.get("F3")); + + System.out.println(main.dump("")); + System.out.println(main.hexDump("")); + System.out.println(main.getParserTree("")); + + } + + + @Test + public void packtest02() throws ISOException { + + + FSDMsgX ifSet = new FSDMsgX("ifSet"); + AFSDFieldPackager f0_a = new FixedFieldPackager("F0", new String(new byte[] { (byte) ';' }), + AsciiInterpreter.INSTANCE); + AFSDFieldPackager f1_a = new FixedFieldPackager("F1", 4, AsciiInterpreter.INSTANCE); + AFSDFieldPackager f2_a = new FixedFieldPackager("F2", 4, AsciiInterpreter.INSTANCE); + + ifSet.add("F1", f1_a); + ifSet.add("F2", f2_a); + ifSet.add("F0", f0_a); + + FSDMsgX ifNotSet = new FSDMsgX("ifnotSet"); + AFSDFieldPackager f1_b = new FixedFieldPackager("F1", 8, AsciiInterpreter.INSTANCE); + ifNotSet.add("F1", f1_b); + + AFSDFieldPackager f3 = new FixedFieldPackager("F3", 3, AsciiInterpreter.INSTANCE); + + FSDMsgX main = new FSDMsgX("main"); + String[] setFields = { "F0" }; + AFSDFieldPackager look = new LookAheadPackager("LA", 8, Byte.valueOf((byte) ';'), ifSet, ifNotSet, setFields, + null); + main.add("LA", look); + main.add("F3", f3); + + main.set("F1", "ABCD1234"); + main.set("F3", "XYZ"); + byte[] outStream = main.pack(); + assertArrayEquals("ABCD1234XYZ".getBytes(), outStream); + + System.out.println(main.dump("")); + System.out.println(main.hexDump("")); + + } + + @Test + public void packtest01() throws ISOException { + + FSDMsgX ifSet = new FSDMsgX("ifSet"); + AFSDFieldPackager f0_a = new FixedFieldPackager("F0", new String(new byte[] { (byte) ';' }), + AsciiInterpreter.INSTANCE); + AFSDFieldPackager f1_a = new FixedFieldPackager("F1", 4, AsciiInterpreter.INSTANCE); + AFSDFieldPackager f2_a = new FixedFieldPackager("F2", 4, AsciiInterpreter.INSTANCE); + + ifSet.add("F1", f1_a); + ifSet.add("F2", f2_a); + ifSet.add("F0", f0_a); + + FSDMsgX ifNotSet = new FSDMsgX("ifnotSet"); + AFSDFieldPackager f1_b = new FixedFieldPackager("F1", 8, AsciiInterpreter.INSTANCE); + ifNotSet.add("F1", f1_b); + + AFSDFieldPackager f3 = new FixedFieldPackager("F3", 3, AsciiInterpreter.INSTANCE); + + FSDMsgX main = new FSDMsgX("main"); + String[] setFields = { "F0" }; + AFSDFieldPackager look = new LookAheadPackager("LA", 8, Byte.valueOf((byte) ';'), ifSet, ifNotSet, setFields, + null); + main.add("LA", look); + main.add("F3", f3); + + main.set("F1", "ABCD"); + main.set("F2", "1234"); + main.set("F3", "XYZ"); + main.set("F0", ";"); + byte[] outStream = main.pack(); + assertArrayEquals("ABCD1234;XYZ".getBytes(), outStream); + + System.out.println(main.dump("")); + System.out.println(main.hexDump("")); + + } + +} diff --git a/modules/fsdmsgx/src/test/java/org/jpos/fsdpackager/VariableFieldPackagerTest.java b/modules/fsdmsgx/src/test/java/org/jpos/fsdpackager/VariableFieldPackagerTest.java new file mode 100644 index 0000000000..193c8507e8 --- /dev/null +++ b/modules/fsdmsgx/src/test/java/org/jpos/fsdpackager/VariableFieldPackagerTest.java @@ -0,0 +1,240 @@ +/* + * jPOS Project [http://jpos.org] + * Copyright (C) 2000-2015 Alejandro P. Revilla + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.jpos.fsdpackager; + +import static org.junit.Assert.*; + +import org.jpos.iso.AsciiInterpreter; +import org.jpos.iso.ISOException; +import org.jpos.iso.ISOUtil; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +public class VariableFieldPackagerTest { + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + /** + * Happy day scenario where a variable field within the max size with a + * field separator is received. The field should be available for use + * without the delimiter. + * + * @throws ISOException + */ + @Test + public void unpackTest01() throws ISOException { + + VariableFieldPackager p = new VariableFieldPackager("F1", 20, new Byte((byte) 0x1c), AsciiInterpreter.INSTANCE); + FSDMsgX msg = new FSDMsgX("Test");; + msg.add("F1", p); + String inStream = "123456" + (char) 0x1c; + msg.unpack(inStream.getBytes()); + + assertEquals("123456", msg.get("F1")); + + } + + /** + * Happy day scenario where a variable field is set without using a + * delimiter. The resulting byte array will have the data and the delimiter + * in it. + * + * @throws ISOException + */ + @Test + public void packTest01() throws ISOException { + + VariableFieldPackager f1 = new VariableFieldPackager("F1", 20, new Byte((byte) 0x1c), + AsciiInterpreter.INSTANCE); + FSDMsgX msg = new FSDMsgX("Test");; + msg.add("F1", f1); + msg.set("F1", "123456"); + + byte[] outStream = msg.pack(); + + assertArrayEquals(("123456" + (char) 0x1c).getBytes(), outStream); + + } + + /** + * Happy day scenario where a 2 variable field within the max size with + * their respective delimiters is received. The field should be available + * for use without the delimiter. + * + * @throws ISOException + */ + @Test + public void unpackTest02() throws ISOException { + + VariableFieldPackager f1 = new VariableFieldPackager("F1", 20, new Byte((byte) 0x1c), + AsciiInterpreter.INSTANCE); + VariableFieldPackager f2 = new VariableFieldPackager("F2", 5, new Byte((byte) 0x1d), AsciiInterpreter.INSTANCE); + + FSDMsgX msg = new FSDMsgX("Test");; + msg.add("F1", f1); + msg.add("F2", f2); + + String inStream = "123456" + (char) 0x1c + "ABC" + (char) 0x1d; + msg.unpack(inStream.getBytes()); + + assertEquals("123456", msg.get("F1")); + assertEquals("ABC", msg.get("F2")); + + } + + /** + * Happy day scenario where a multiple variable fields are set without using + * a delimiter. The resulting byte array will have the data of the fields + * with their respective delimiters in it. + * + * @throws ISOException + */ + + @Test + public void packTest02() throws ISOException { + + VariableFieldPackager f1 = new VariableFieldPackager("F1", 20, new Byte((byte) 0x1c), + AsciiInterpreter.INSTANCE); + VariableFieldPackager f2 = new VariableFieldPackager("F2", 5, new Byte((byte) 0x1d), AsciiInterpreter.INSTANCE); + + FSDMsgX msg = new FSDMsgX("Test");; + msg.add("F1", f1); + msg.add("F2", f2); + + msg.set("F1", "123456"); + msg.set("F2", "ABC"); + + byte[] outStream = msg.pack(); + + assertArrayEquals(("123456" + (char) 0x1c + "ABC" + (char) 0x1d).getBytes(), outStream); + + } + + /** + * The order of the packed fields is dependent on the FSDMsg2's add. Setting + * of fields can be in any order. + * + * @throws ISOException + */ + @Test + public void packTest03() throws ISOException { + + VariableFieldPackager f1 = new VariableFieldPackager("F1", 20, new Byte((byte) 0x1c), + AsciiInterpreter.INSTANCE); + VariableFieldPackager f2 = new VariableFieldPackager("F2", 5, new Byte((byte) 0x1d), AsciiInterpreter.INSTANCE); + + FSDMsgX msg = new FSDMsgX("Test");; + msg.add("F1", f1); + msg.add("F2", f2); + + msg.set("F2", "ABC"); + msg.set("F1", "123456"); + + byte[] outStream = msg.pack(); + + assertArrayEquals(("123456" + (char) 0x1c + "ABC" + (char) 0x1d).getBytes(), outStream); + + } + + /** + * Field size can be upto 20 followed by delimiter. The data available is 25 + * wide and no delimiter. An exception should be thrown indicating a + * delimiter wasnt found after the max of 20 allowed. + * + * @throws ISOException + */ + @Test + public void unpackTest03() throws ISOException { + + thrown.expect(ISOException.class); + thrown.expectMessage("Field [F1]: Delimiter 1c not present after max size 20"); + + VariableFieldPackager p = new VariableFieldPackager("F1", 20, new Byte((byte) 0x1c), AsciiInterpreter.INSTANCE); + FSDMsgX msg = new FSDMsgX("Test");; + msg.add("F1", p); + + String inStream = ISOUtil.padleft("", 25, '1') + (char) 0x1c; + msg.unpack(inStream.getBytes()); + + } + + /** + * If a variable stream comes in with data that reaches end of stream and + * does not contain a delimitter its valid. There is no point to have a + * delimiter at the end of a field if its the last field. + * + * @throws ISOException + */ + @Test + public void unpackTest04() throws ISOException { + + VariableFieldPackager p = new VariableFieldPackager("F1", 20, new Byte((byte) 0x1c), AsciiInterpreter.INSTANCE); + FSDMsgX msg = new FSDMsgX("Test");; + msg.add("F1", p); + + String inStream = ISOUtil.padleft("", 10, '1'); + msg.unpack(inStream.getBytes()); + + assertEquals(inStream, msg.get("F1")); + + } + + /** + * variable fields indicate their presence with the delimiter. If there is + * no data a delimiter needs to be sent indicating the presence of the field + * with no data. The field will be set with an empty string. + * + * @throws ISOException + */ + @Test + public void unpackTest05() throws ISOException { + + VariableFieldPackager p = new VariableFieldPackager("F1", 20, new Byte((byte) 0x1c), AsciiInterpreter.INSTANCE); + FSDMsgX msg = new FSDMsgX("Test");; + msg.add("F1", p); + + String inStream = new String(new byte[] { 0x1c }); + msg.unpack(inStream.getBytes()); + + assertEquals("", msg.get("F1")); + + } + + /** + * At time of packing if the field is not set, make sure that the delimiter + * is still available. + * + * @throws ISOException + */ + @Test + public void packTest04() throws ISOException { + + VariableFieldPackager p = new VariableFieldPackager("F1", 20, new Byte((byte) 0x1c), AsciiInterpreter.INSTANCE); + FSDMsgX msg = new FSDMsgX("Test");; + msg.add("F1", p); + + byte[] outStream = msg.pack(); + + assertArrayEquals(new byte[] { 0x1c }, outStream); + + } + +} diff --git a/settings.gradle b/settings.gradle index 127e228e84..26d3e1db08 100644 --- a/settings.gradle +++ b/settings.gradle @@ -23,7 +23,8 @@ include ':modules:core',\ ':modules:visitor', \ ':modules:rspace', \ ':modules:testbed', \ - ':modules:eerest' + ':modules:eerest', \ + ':modules:fsdmsgx' rootProject.name = 'jposee'