55import java .util .Arrays ;
66import java .util .BitSet ;
77import java .util .Collection ;
8+ import java .util .Comparator ;
9+ import java .util .EnumMap ;
810import java .util .EnumSet ;
11+ import java .util .HashMap ;
912import java .util .HashSet ;
1013import java .util .List ;
1114import java .util .Map ;
15+ import java .util .Map .Entry ;
1216import java .util .Set ;
17+ import java .util .regex .Matcher ;
18+ import java .util .regex .Pattern ;
1319
1420import biblemulticonverter .data .Bible ;
1521import biblemulticonverter .data .Book ;
1622import biblemulticonverter .data .BookID ;
1723import biblemulticonverter .data .Chapter ;
1824import biblemulticonverter .data .FormattedText ;
1925import biblemulticonverter .data .FormattedText .Visitor ;
26+ import biblemulticonverter .data .Utils ;
2027import biblemulticonverter .data .Verse ;
2128import biblemulticonverter .data .VerseRange ;
2229import biblemulticonverter .data .VirtualVerse ;
@@ -32,13 +39,15 @@ public void doExport(Bible bible, String... exportArgs) throws Exception {
3239 Set <String > totalVerses = new HashSet <String >();
3340 boolean includeXref = exportArgs .length > 0 && exportArgs [0 ].equals ("-xref" );
3441 Set <BookID > usedBooks = EnumSet .noneOf (BookID .class );
42+ Map <BookID ,String > bookAbbrMap = new EnumMap <>(BookID .class );
3543 XrefCountVisitor xcv = includeXref ? new XrefCountVisitor (schemes , totalVerses , usedBooks ) : null ;
3644 int usedArgCount = (includeXref ? 1 : 0 );
3745 boolean limitBooks = exportArgs .length > usedArgCount && exportArgs [usedArgCount ].equals ("-limitBooks" );
3846
3947 // fill missing verses
4048 for (Book book : bible .getBooks ()) {
4149 usedBooks .add (book .getId ());
50+ bookAbbrMap .put (book .getId (), book .getAbbr ());
4251 for (int cc = 0 ; cc < book .getChapters ().size (); cc ++) {
4352 Chapter chapter = book .getChapters ().get (cc );
4453 if (includeXref && chapter .getProlog () != null ) {
@@ -76,13 +85,14 @@ public void doExport(Bible bible, String... exportArgs) throws Exception {
7685
7786 // print them
7887 System .out .print ("Best match: " );
79- int totalVerseCount = totalVerses .size ();
80- printScheme (schemes [0 ], totalVerseCount );
88+ String verboseSchemasProperty = System .getProperty ("versificationdetector.verboseschemes" , "" );
89+ Set <String > verboseSchemes = verboseSchemasProperty == null ? null : new HashSet <>(Arrays .asList (verboseSchemasProperty .split (", *" )));
90+ printScheme (schemes [0 ], totalVerses , verboseSchemes , bookAbbrMap );
8191
8292 System .out .println ();
8393 System .out .println ("Other options:" );
8494 for (int i = 1 ; i < Math .min (11 , schemes .length ); i ++) {
85- printScheme (schemes [i ], totalVerseCount );
95+ printScheme (schemes [i ], totalVerses , verboseSchemes , bookAbbrMap );
8696 if (schemes [i ].missingChapters .size () > schemes [0 ].missingChapters .size () + 2 ||
8797 schemes [i ].missingVerses .size () > schemes [0 ].missingVerses .size () + 5 )
8898 break ;
@@ -96,7 +106,7 @@ public void doExport(Bible bible, String... exportArgs) throws Exception {
96106 boolean found = false ;
97107 for (VersificationScheme scheme : schemes ) {
98108 if (scheme .getName ().equals (exportArgs [i ])) {
99- printScheme (scheme , totalVerseCount );
109+ printScheme (scheme , totalVerses , verboseSchemes , bookAbbrMap );
100110 found = true ;
101111 break ;
102112 }
@@ -134,13 +144,51 @@ protected boolean useTitleAsVerseZero() {
134144 return false ;
135145 }
136146
137- private void printScheme (VersificationScheme scheme , int totalVerseCount ) {
147+ private void printScheme (VersificationScheme scheme , Set < String > totalVerses , Set < String > verboseSchemes , Map < BookID , String > bookAbbrMap ) {
138148 if (scheme .getMissingChapters ().size () > 0 )
139149 System .out .println (scheme .getName () + " (Missing chapters+verses: " + scheme .getMissingChapters ().size () + "+" + scheme .getMissingVerses ().size () + " " + scheme .getMissingChapters () + " " + scheme .getMissingVerses ());
140150 else if (scheme .getMissingVerses ().size () > 0 )
141151 System .out .println (scheme .getName () + " (Missing verses: " + scheme .getMissingVerses ().size () + " " + scheme .getMissingVerses () + ")" );
142152 else
143- System .out .println (scheme .getName () + " (All verses covered, and " + (scheme .getVerseCount () - totalVerseCount ) + " more)" );
153+ System .out .println (scheme .getName () + " (All verses covered, and " + (scheme .getVerseCount () - totalVerses .size ()) + " more)" );
154+ if (verboseSchemes != null && (verboseSchemes .contains (scheme .getName ()) || verboseSchemes .contains ("all" ))) {
155+ Set <String > coveredVerses = new HashSet <>();
156+ for (Entry <BookID , BitSet []> entry : scheme .coveredBooks .entrySet ()) {
157+ String bookAbbr = bookAbbrMap .getOrDefault (entry .getKey (), entry .getKey ().getOsisID ());
158+ for (int cnum = 1 ; cnum <= entry .getValue ().length ; cnum ++) {
159+ BitSet verses = entry .getValue ()[cnum - 1 ];
160+ for (int vnum = verses .nextSetBit (0 ); vnum != -1 ; vnum = verses .nextSetBit (vnum + 1 )) {
161+ coveredVerses .add (bookAbbr + " " + cnum + ":" + vnum );
162+ }
163+ }
164+ }
165+ List <String > bookAbbrOrder = new ArrayList <>(bookAbbrMap .values ());
166+ printVerbose ("\t -" , totalVerses , coveredVerses , bookAbbrOrder );
167+ printVerbose ("\t +" , coveredVerses , totalVerses , bookAbbrOrder );
168+ }
169+ }
170+
171+ private void printVerbose (String prefix , Set <String > verseList , Set <String > removeList , List <String > bookAbbrOrder ) {
172+ List <String > list = new ArrayList <>(verseList );
173+ list .removeAll (removeList );
174+ Map <String , int []> sortKey = new HashMap <>();
175+ Pattern ptn = Pattern .compile ("(" + Utils .BOOK_ABBR_REGEX + ") ([0-9]+):([0-9]+)" );
176+ for (String verse : list ) {
177+ Matcher m = ptn .matcher (verse );
178+ if (!m .matches ())
179+ throw new RuntimeException ("Invalid verse reference: " + verse );
180+ String abbr = m .group (1 );
181+ int aidx = bookAbbrOrder .indexOf (abbr );
182+ if (aidx == 0 ) {
183+ aidx = bookAbbrOrder .size ();
184+ bookAbbrOrder .add (abbr );
185+ }
186+ sortKey .put (verse , new int [] { aidx , Integer .parseInt (m .group (2 )), Integer .parseInt (m .group (3 )) });
187+ }
188+ list .sort (Comparator .comparing (v -> sortKey .get (v ), Comparator .<int [], Integer > comparing (a -> a [0 ]).thenComparing (a -> a [1 ]).thenComparing (a -> a [2 ])));
189+ for (String verse : list ) {
190+ System .out .println (prefix + verse );
191+ }
144192 }
145193
146194 public static final class VersificationScheme implements Comparable <VersificationScheme > {
0 commit comments