6868import java .util .ArrayList ;
6969import java .util .Arrays ;
7070import java .util .Collection ;
71- import java .util .Comparator ;
71+ import java .util .HashMap ;
7272import java .util .List ;
73+ import java .util .Map ;
7374import java .util .stream .Collectors ;
7475
7576/**
@@ -664,52 +665,90 @@ public static List<SourceAndConverter<?>> sortDefaultGeneric(
664665 List <SourceAndConverter <?>> sortedList = new ArrayList <>(sacs .size ());
665666 sortedList .addAll (sacs );
666667
667- Comparator <SourceAndConverter <?>> sacComparator = (s1 , s2 ) -> {
668- // Those who do not belong to spimdata are last:
669- SourceAndConverterService .SpimDataInfo sdi1 = null , sdi2 = null ;
670- if (SourceAndConverterServices .getSourceAndConverterService ().getMetadata (
671- s1 , SourceAndConverterService .SPIM_DATA_INFO ) != null )
672- {
673- sdi1 =
674- ((SourceAndConverterService .SpimDataInfo ) (SourceAndConverterServices
675- .getSourceAndConverterService ().getMetadata (s1 ,
676- SourceAndConverterService .SPIM_DATA_INFO )));
677- }
668+ // Build a map of asd objects to unique IDs for stable ordering
669+ final Map <Object , Integer > asdIdMap = new HashMap <>();
670+ final Map <SourceAndConverter <?>, ComparableKey > keyMap = new HashMap <>();
678671
679- if (SourceAndConverterServices .getSourceAndConverterService ().getMetadata (
680- s2 , SourceAndConverterService .SPIM_DATA_INFO ) != null )
681- {
682- sdi2 =
683- ((SourceAndConverterService .SpimDataInfo ) (SourceAndConverterServices
684- .getSourceAndConverterService ().getMetadata (s2 ,
685- SourceAndConverterService .SPIM_DATA_INFO )));
686- }
672+ int index = 0 ;
673+ int nextAsdId = 0 ;
687674
688- if (( sdi1 == null ) && ( sdi2 != null ) ) {
689- return - 1 ;
690- }
675+ for ( SourceAndConverter <?> sac : sortedList ) {
676+ Object metadata = SourceAndConverterServices . getSourceAndConverterService ()
677+ . getMetadata ( sac , SourceAndConverterService . SPIM_DATA_INFO );
691678
692- if ((sdi1 != null ) && (sdi2 == null )) {
693- return 1 ;
694- }
679+ ComparableKey key ;
680+ if (metadata != null ) {
681+ SourceAndConverterService .SpimDataInfo sdi =
682+ (SourceAndConverterService .SpimDataInfo ) metadata ;
695683
696- if (sdi1 != null ) {
697- if (sdi1 .asd == sdi2 .asd ) {
698- return sdi1 .setupId - sdi2 .setupId ;
699- }
700- else {
701- return sdi2 .toString ().compareTo (sdi1 .toString ());
684+ // Assign a stable ID to each unique asd object
685+ if (!asdIdMap .containsKey (sdi .asd )) {
686+ asdIdMap .put (sdi .asd , nextAsdId ++);
702687 }
688+ int asdId = asdIdMap .get (sdi .asd );
689+
690+ // Create key: has SpimData (0), asd ID, setupId, then index as tiebreaker
691+ key = new ComparableKey (0 , asdId , sdi .setupId , "" , index );
692+ } else {
693+ // No SpimData: use (1) to sort after SpimData sources, then by name
694+ String name = sac .getSpimSource ().getName ();
695+ if (name == null ) name = "" ;
696+ key = new ComparableKey (1 , 0 , 0 , name , index );
703697 }
704698
705- return s2 .getSpimSource ().getName ().compareTo (s1 .getSpimSource ()
706- .getName ());
707- };
699+ keyMap .put (sac , key );
700+ index ++;
701+ }
702+
703+ // Sort using the comparable keys
704+ sortedList .sort ((s1 , s2 ) -> {
705+ ComparableKey key1 = keyMap .get (s1 );
706+ ComparableKey key2 = keyMap .get (s2 );
707+ if (key1 == null || key2 == null ) {
708+ if (key1 == null && key2 == null ) return 0 ;
709+ return (key1 == null ) ? 1 : -1 ;
710+ }
711+ return key1 .compareTo (key2 );
712+ });
708713
709- sortedList .sort (sacComparator );
710714 return sortedList ;
711715 }
712716
717+ // Comparable key for guaranteed transitive sorting
718+ private static class ComparableKey implements Comparable <ComparableKey > {
719+ final int group ; // 0 = has SpimData, 1 = no SpimData
720+ final int asdId ; // Stable ID for asd object (0 if no SpimData)
721+ final int setupId ; // Setup ID within same asd (0 if no SpimData)
722+ final String name ; // Name for sources without SpimData
723+ final int index ; // Original index as final tiebreaker
724+
725+ ComparableKey (int group , int asdId , int setupId , String name , int index ) {
726+ this .group = group ;
727+ this .asdId = asdId ;
728+ this .setupId = setupId ;
729+ this .name = name ;
730+ this .index = index ;
731+ }
732+
733+ @ Override
734+ public int compareTo (ComparableKey other ) {
735+ // Compare level by level to ensure transitivity
736+ int cmp = Integer .compare (this .group , other .group );
737+ if (cmp != 0 ) return cmp ;
738+
739+ cmp = Integer .compare (this .asdId , other .asdId );
740+ if (cmp != 0 ) return cmp ;
741+
742+ cmp = Integer .compare (this .setupId , other .setupId );
743+ if (cmp != 0 ) return cmp ;
744+
745+ cmp = this .name .compareTo (other .name );
746+ if (cmp != 0 ) return cmp ;
747+
748+ return Integer .compare (this .index , other .index );
749+ }
750+ }
751+
713752 /**
714753 * Default sorting order for SourceAndConverter Because sometimes we want some
715754 * consistency in channel ordering when exporting / importing TODO : find a
@@ -726,49 +765,52 @@ public static List<SourceAndConverter> sortDefaultNoGeneric(
726765 List <SourceAndConverter > sortedList = new ArrayList <>(sacs .size ());
727766 sortedList .addAll (sacs );
728767
729- Comparator <SourceAndConverter > sacComparator = (s1 , s2 ) -> {
730- // Those who do not belong to spimdata are last:
731- SourceAndConverterService .SpimDataInfo sdi1 = null , sdi2 = null ;
732- if (SourceAndConverterServices .getSourceAndConverterService ().getMetadata (
733- s1 , SourceAndConverterService .SPIM_DATA_INFO ) != null )
734- {
735- sdi1 =
736- ((SourceAndConverterService .SpimDataInfo ) (SourceAndConverterServices
737- .getSourceAndConverterService ().getMetadata (s1 ,
738- SourceAndConverterService .SPIM_DATA_INFO )));
739- }
768+ // Build a map of asd objects to unique IDs for stable ordering
769+ final Map <Object , Integer > asdIdMap = new HashMap <>();
770+ final Map <SourceAndConverter , ComparableKey > keyMap = new HashMap <>();
740771
741- if (SourceAndConverterServices .getSourceAndConverterService ().getMetadata (
742- s2 , SourceAndConverterService .SPIM_DATA_INFO ) != null )
743- {
744- sdi2 =
745- ((SourceAndConverterService .SpimDataInfo ) (SourceAndConverterServices
746- .getSourceAndConverterService ().getMetadata (s2 ,
747- SourceAndConverterService .SPIM_DATA_INFO )));
748- }
772+ int index = 0 ;
773+ int nextAsdId = 0 ;
749774
750- if (( sdi1 == null ) && ( sdi2 != null ) ) {
751- return - 1 ;
752- }
775+ for ( SourceAndConverter sac : sortedList ) {
776+ Object metadata = SourceAndConverterServices . getSourceAndConverterService ()
777+ . getMetadata ( sac , SourceAndConverterService . SPIM_DATA_INFO );
753778
754- if ((sdi1 != null ) && (sdi2 == null )) {
755- return 1 ;
756- }
779+ ComparableKey key ;
780+ if (metadata != null ) {
781+ SourceAndConverterService .SpimDataInfo sdi =
782+ (SourceAndConverterService .SpimDataInfo ) metadata ;
757783
758- if (sdi1 != null ) {
759- if (sdi1 .asd == sdi2 .asd ) {
760- return sdi1 .setupId - sdi2 .setupId ;
761- }
762- else {
763- return sdi2 .toString ().compareTo (sdi1 .toString ());
784+ // Assign a stable ID to each unique asd object
785+ if (!asdIdMap .containsKey (sdi .asd )) {
786+ asdIdMap .put (sdi .asd , nextAsdId ++);
764787 }
788+ int asdId = asdIdMap .get (sdi .asd );
789+
790+ // Create key: has SpimData (0), asd ID, setupId, then index as tiebreaker
791+ key = new ComparableKey (0 , asdId , sdi .setupId , "" , index );
792+ } else {
793+ // No SpimData: use (1) to sort after SpimData sources, then by name
794+ String name = sac .getSpimSource ().getName ();
795+ if (name == null ) name = "" ;
796+ key = new ComparableKey (1 , 0 , 0 , name , index );
765797 }
766798
767- return s2 .getSpimSource ().getName ().compareTo (s1 .getSpimSource ()
768- .getName ());
769- };
799+ keyMap .put (sac , key );
800+ index ++;
801+ }
802+
803+ // Sort using the comparable keys
804+ sortedList .sort ((s1 , s2 ) -> {
805+ ComparableKey key1 = keyMap .get (s1 );
806+ ComparableKey key2 = keyMap .get (s2 );
807+ if (key1 == null || key2 == null ) {
808+ if (key1 == null && key2 == null ) return 0 ;
809+ return (key1 == null ) ? 1 : -1 ;
810+ }
811+ return key1 .compareTo (key2 );
812+ });
770813
771- sortedList .sort (sacComparator );
772814 return sortedList ;
773815 }
774816
0 commit comments