diff --git a/jpos/src/main/java/org/jpos/iso/ISOMsg.java b/jpos/src/main/java/org/jpos/iso/ISOMsg.java index b5f75ca704..b200134f16 100644 --- a/jpos/src/main/java/org/jpos/iso/ISOMsg.java +++ b/jpos/src/main/java/org/jpos/iso/ISOMsg.java @@ -285,32 +285,34 @@ public void set(String fpath, String value) { * @param c component * @throws ISOException on error */ - public void set (String fpath, ISOComponent c) throws ISOException { - StringTokenizer st = new StringTokenizer (fpath, "."); - ISOMsg m = this; - for (;;) { - int fldno = parseInt(st.nextToken()); - if (st.hasMoreTokens()) { - Object obj = m.getValue(fldno); - if (obj instanceof ISOMsg) - m = (ISOMsg) obj; - else - /* - * we need to go deeper, however, if the value == null then - * there is nothing to do (unset) at the lower levels, so break now and save some processing. - */ - if (c == null) { - break; - } else { - // We have a value to set, so adding a level to hold it is sensible. - m.set (m = new ISOMsg (fldno)); - } - } else { - m.set (c); - break; - } - } - } + public void set(String fpath, ISOComponent c) throws ISOException { + StringTokenizer st = new StringTokenizer (fpath, "."); + ISOMsg m = this; + for (;;) { + int fldno = parseInt(st.nextToken()); + if (st.hasMoreTokens()) { + Object obj = m.getValue(fldno); + if (obj instanceof ISOMsg) + m = (ISOMsg) obj; + else + /* + * we need to go deeper, however, if the value == null then + * there is nothing to do (unset) at the lower levels, so break now and save some processing. + */ + if (c == null) { + break; + } else { + // We have a value to set, so adding a level to hold it is sensible. + m.set(m = new ISOMsg(fldno)); + } + } else { + if (c != null) + c.setFieldNumber(fldno); + m.set(c); + break; + } + } + } /** * Creates an ISOField associated with fldno within this ISOMsg. @@ -520,7 +522,7 @@ public void dump (PrintStream p, String indent) { ((Loggeable) header).dump (p, newIndent); for (int i : fields.keySet()) { - //If you want the bitmap dumped in the log, change the condition from (i >= 0) to (i >= -1). + //If you want the bitmap dumped in the log, change the condition from (i >= 0) to (i >= -1). if (i >= 0) { if ((c = (ISOComponent) fields.get(i)) != null) c.dump(p, newIndent); diff --git a/jpos/src/test/java/org/jpos/iso/ISOMsgTest.java b/jpos/src/test/java/org/jpos/iso/ISOMsgTest.java index 6b32d935ae..a5d2982c65 100644 --- a/jpos/src/test/java/org/jpos/iso/ISOMsgTest.java +++ b/jpos/src/test/java/org/jpos/iso/ISOMsgTest.java @@ -18,9 +18,7 @@ package org.jpos.iso; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.*; import org.junit.jupiter.api.Test; @@ -42,24 +40,24 @@ public void testGetBytes() throws Exception { assertEquals ("Field 63.2.3", m.getString ("63.2.3")); assertEquals ("CAFEBABE", new String(m.getBytes("63.2.4"))); } - + @Test public void testFPath() throws Exception { ISOMsg m = new ISOMsg("0100"); - + String mynull = null; - + assertFalse(m.hasField("63")); assertFalse(m.hasField(63)); assertFalse(m.hasField("63.2")); assertFalse(m.hasField("63.2.3")); - + m.set("63.2.3","value3"); m.set("63.2.4","value4"); - + /* * Check null processing on set matches existing processing (setting to null same as unset). - * + * * Please note m.set(fPathString,null) is amiguous and cannot be distinguished from * m.set(fieldNumberString, byte[]), so take care. */ @@ -67,103 +65,155 @@ public void testFPath() throws Exception { m.set("63.2.6",m.getString("99")); // null as well assertFalse(m.hasField("63.2.5")); assertFalse(m.hasField("63.2.6")); - + assertEquals(true,m.hasField("63.2.3")); assertEquals("value3", m.getString("63.2.3")); assertEquals(true,m.hasField("63.2.4")); assertEquals("value4", m.getString("63.2.4")); - + assertFalse(m.hasField("63.2.999")); assertFalse(m.hasField("63.2.4.999")); - + m.unset("63.2.3"); - + assertFalse(m.hasField("63.2.3")); - + assertEquals(true,m.hasField("63.2")); m.unset("63.2.4"); // Removal of last remaining field triggers removal of immediate parent. assertFalse(m.hasField("63.2")); - + m.unset("63.2.4.999"); // No problem removing non-existant fields. - + assertFalse(m.hasField("99")); assertFalse(m.hasField(99)); m.set("99.99","value99"); m.set("99.98",mynull); - + assertEquals(true, m.hasField("99.99")); assertEquals("value99", m.getString("99.99")); - + assertFalse(m.hasField("100")); assertFalse(m.hasField(100)); m.set("100.100",mynull); assertFalse(m.hasField("100.100")); assertFalse(m.hasField("100")); // Not added unnecessarily assertFalse(m.hasField(100)); // Still not added unnecessarily - + } - + @Test public void testFPathISOComponent() throws Exception { ISOMsg m = new ISOMsg("0100"); ISOField f100 = new ISOField(100,"value100"); - + assertFalse(m.hasField("100")); assertFalse(m.hasField(100)); m.set(f100); - assertEquals(true, m.hasField("100")); - assertEquals(true, m.hasField(100)); + assertTrue(m.hasField("100")); + assertTrue(m.hasField(100)); assertEquals(f100,m.getComponent("100")); - + assertFalse(m.hasField("101")); assertFalse(m.hasField(101)); m.set("101.101","value101"); - assertEquals(true, m.hasField("101.101")); - assertEquals(true, m.hasField("101")); - assertEquals(true, m.hasField(101)); + assertTrue(m.hasField("101.101")); + assertTrue(m.hasField("101")); + assertTrue(m.hasField(101)); assertEquals(101,m.getComponent("101.101").getKey()); assertEquals("value101", m.getComponent("101.101").getValue()); m.set("101.102","value102"); - assertEquals(true, m.hasField("101.102")); + assertTrue(m.hasField("101.102")); assertEquals(102,m.getComponent("101.102").getKey()); assertEquals("value102", m.getComponent("101.102").getValue()); ISOMsg f102 = new ISOMsg(102); f102.set("1","value1"); f102.set("2","value2"); - + assertFalse(m.hasField("102")); m.set(f102); - assertEquals(true, m.hasField("102.1")); - assertEquals(true, m.hasField("102.2")); - + assertTrue(m.hasField("102.1")); + assertTrue(m.hasField("102.2")); + ISOMsg copy = new ISOMsg(); copy.set("101",m.getComponent("101")); - assertEquals(true, copy.hasField("101")); - assertEquals(true, copy.hasField(101)); - assertEquals(true, copy.hasField("101.101")); - assertEquals(true, copy.hasField("101.102")); + assertTrue(copy.hasField("101")); + assertTrue(copy.hasField(101)); + assertTrue(copy.hasField("101.101")); + assertTrue(copy.hasField("101.102")); assertEquals("value101",copy.getString("101.101")); assertEquals("value102",copy.getString("101.102")); - + copy.set("102.1", m.getComponent("102.1")); - assertEquals(true, copy.hasField("102")); - assertEquals(true, copy.hasField(102)); - assertEquals(true, copy.hasField("102.1")); + assertTrue(copy.hasField("102")); + assertTrue(copy.hasField(102)); + assertTrue(copy.hasField("102.1")); assertEquals("value1",copy.getString("102.1")); assertFalse(copy.hasField("102.2")); assertNull(copy.getString("102.2")); } - + + @Test + public void testFPathISOComponent_2() throws Exception { + ISOAmount comp = new ISOAmount(); + comp.setValue("840"+"2"+"000055555533"); + assertEquals(-1, comp.getFieldNumber()); + + ISOMsg m = new ISOMsg(); + m.set(44, "hello44"); + m.set("95.2.8", comp); + + assertTrue(m.hasField(95)); + assertTrue(m.hasField("95")); + assertNotNull(m.getComponent(95)); + + assertTrue(m.hasField("95.2")); + assertTrue(m.hasField("95.2.8")); + + ISOComponent extractedComp = m.getComponent("95.2.8"); + assertEquals(comp, extractedComp); + assertEquals(8, extractedComp.getFieldNumber()); + assertEquals("840", ((ISOAmount)extractedComp).getCurrencyCodeAsString()); + + ISOAmount comp2 = new ISOAmount(99); + comp2.setValue("858"+"2"+"000011111177"); + + assertEquals(99, comp2.getFieldNumber()); + m.set("95.2.10", comp2); + + // the set method above should have changed comp2's inner field number to the last value in the path + assertEquals(10, comp2.getFieldNumber()); + + assertNotNull(m.getComponent("95.2.10")); + assertEquals(comp2, m.getComponent("95.2.10")); + + assertEquals(10, m.getComponent("95.2").getMaxField()); + assertEquals( 2, m.getComponent("95.2").getChildren().size()); + assertEquals(858, ((ISOAmount)m.getComponent("95.2.10")).getCurrencyCode()); + + m.set("95.2.8", (String)null); + assertEquals(1, m.getComponent("95.2").getChildren().size()); + assertEquals(858, ((ISOAmount)m.getComponent("95.2.10")).getCurrencyCode()); + + m.unset("95.2.10"); + // The way ISOMsg#unset(fpath) works, is that if the parent of the unset sub-subfield becomes + // empty, it will also delete the parent! But the behaviour doesn't propagate up the hierarchy... + assertFalse(m.hasField("95.2")); + + // ...therefore, 95 should still exist (along with the root ISOMsg, of course) + assertTrue(m.hasField("95")); + assertTrue(m.getComponent("95").getChildren().isEmpty()); + } + @Test public void testFPathISOEcho() throws Exception { ISOMsg m = new ISOMsg("0100"); - + ISOField f100 = new ISOField(100,"value100"); m.set(f100); - + m.set("101.101","value101"); m.set("101.102","value102"); @@ -171,7 +221,7 @@ public void testFPathISOEcho() throws Exception { f102.set("1","value1"); f102.set("2","value2"); m.set(f102); - + ISOMsg f103 = new ISOMsg(103); f103.set("97","value1"); f103.set("98","value2"); @@ -185,15 +235,15 @@ public void testFPathISOEcho() throws Exception { m.set(14,"14"); m.set(15,"15"); m.set(16,"16"); - + String[] echoList = new String[] {"10","11","16","14","101.102","103","911.911","999"}; - + ISOMsg copyMsg = new ISOMsg(); - + for (String fpath : echoList) { copyMsg.set(fpath, m.getComponent(fpath)); } - + /* * Check fields in echoMsg */ @@ -212,8 +262,8 @@ public void testFPathISOEcho() throws Exception { assertEquals(true,copyMsg.hasField(103)); // Whole of 103 copied assertEquals(true,copyMsg.hasField("103.97")); // Whole of 103 copied assertEquals(true,copyMsg.hasField("103.98")); // Whole of 103 copied - - + + /* * Check fields echod but *not* present in m are not somehow present in copyMsg */ @@ -222,7 +272,7 @@ public void testFPathISOEcho() throws Exception { assertFalse(copyMsg.hasField("911.911")); assertFalse(copyMsg.hasField("999")); assertFalse(copyMsg.hasField(999)); - + /* * Check fields present in m but not required to be copied are not present in copyMsg */