66import java .util .Iterator ;
77import java .util .List ;
88import java .util .Objects ;
9+ import java .util .Set ;
10+ import java .util .TreeSet ;
911import java .util .stream .Collectors ;
1012
13+ import com .imsweb .x12 .converters .ElementConverter ;
14+ import com .imsweb .x12 .mapping .LoopDefinition ;
15+ import com .imsweb .x12 .mapping .Positioned ;
16+ import com .imsweb .x12 .mapping .SegmentDefinition ;
1117import com .thoughtworks .xstream .XStream ;
1218import com .thoughtworks .xstream .annotations .XStreamAlias ;
1319import com .thoughtworks .xstream .annotations .XStreamOmitField ;
1925import com .thoughtworks .xstream .security .NoTypePermission ;
2026import com .thoughtworks .xstream .security .WildcardTypePermission ;
2127
22- import com .imsweb .x12 .converters .ElementConverter ;
23-
2428/**
2529 * The Loop class is the representation of an Loop in a ANSI X12 transaction. The building block of an X12 transaction is an element. Some
2630 * elements may be made of sub elements. Elements combine to form segments. Segments are grouped as loops. And a set of loops form an X12
@@ -567,7 +571,9 @@ public Loop findTopParentById(String parentId) {
567571 }
568572
569573 /**
570- * Returns the Loop in X12 String format. This method is used to convert the X12 object into a X12 transaction.
574+ * Returns an X12 String for this loop, but it will not be
575+ * properly ordered. For properly ordered X12 string use toX12String.
576+ *
571577 * @return String representation
572578 */
573579 @ Override
@@ -584,6 +590,71 @@ public String toString() {
584590 return dump .toString ();
585591 }
586592
593+ /**
594+ * Returns the Loop in X12 String format. This method is used to convert the X12 object into a X12 transaction.
595+ *
596+ * This will first go through each segment and will return the properly separated string for the segment.
597+ *
598+ * After the segments are seriaized to X12 strings, it will then go through the Loops (in the correct order) and
599+ * recursively call this function for the child loops.
600+ *
601+ * @param loopDefinition The definition of the loop that we are currently on.
602+ * @return String representation The segments from this loop, including child loops.
603+ */
604+ public String toX12String (LoopDefinition loopDefinition ) {
605+ StringBuilder dump = new StringBuilder ();
606+
607+ Set <Positioned > segmentsAndLoops = new TreeSet <>();
608+ if (loopDefinition .getLoop () != null ) {
609+ segmentsAndLoops .addAll (loopDefinition .getLoop ());
610+ }
611+ if (loopDefinition .getSegment () != null ) {
612+ segmentsAndLoops .addAll (loopDefinition .getSegment ());
613+ }
614+ for (Positioned positioned : segmentsAndLoops ) {
615+ if (positioned instanceof SegmentDefinition ) {
616+ SegmentDefinition segmentDefinition = (SegmentDefinition )positioned ;
617+ int idx = 0 ;
618+ Segment segment ;
619+ while ((segment = getSegment (segmentDefinition .getXid (), idx ++)) != null ) {
620+ dump .append (segment );
621+ dump .append (_separators .getSegment ());
622+ dump .append (_separators .getLineBreak ().getLineBreakString ());
623+ }
624+ }
625+ else if (positioned instanceof LoopDefinition ) {
626+ LoopDefinition innerLoopDefinition = (LoopDefinition )positioned ;
627+ int idx = 0 ;
628+ Loop innerLoop ;
629+ while ((innerLoop = getLoopForPrinting (innerLoopDefinition , idx ++)) != null ) {
630+ dump .append (innerLoop .toX12String (innerLoopDefinition ));
631+ }
632+ }
633+ }
634+ return dump .toString ();
635+ }
636+
637+ /**
638+ * Send a LoopDefinition and the index of an loop, fetch the loop from the
639+ * child loops that matches, given that the parentLoop has this loop as a child.
640+ * @param loopDefinition Loop definition for this spot in the x12 document.
641+ * @param idx The index of the loops returned thus far.
642+ * @return The child loop from the loops, or null otherwise.
643+ */
644+ private Loop getLoopForPrinting (LoopDefinition loopDefinition , int idx ) {
645+ Loop loop = getLoop (loopDefinition .getXid (), idx );
646+
647+ // We need to check that the loop we have gotten from getLoop
648+ // is actually a direct child of the current loop we are processing from the
649+ // loop definition.
650+
651+ if (loop != null && _loops .stream ().noneMatch (parentLoop -> parentLoop .getId ().equals (loop .getId ()))) {
652+ return null ;
653+ }
654+
655+ return loop ;
656+ }
657+
587658 /**
588659 * Returns the Loop in XML String format.
589660 * @return XML String
0 commit comments