package com.hemju.biborder; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Reader; import java.io.Writer; import java.util.Arrays; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; /** * Sorts bib reference at the end of the file. * * @author Helmut Juskewycz */ public class OrderBibRef implements OrderStrategy { private static final char[] FOOTNOTE = {'@', 'f', 'o', 'o', 't', 'n', 'o', 't', 'e', ':', '\n'}; private static final int WRITE_BUFFER_SIZE = 1024 * 16; private static final int READ_BUFFER_SIZE = 1024 * 16; private static final int BIB_REF_BUFFER_SIZE = 1024 * 2;//Note that is the maximum size of a bib reference entry private static final char[] READ_BUFFER = new char[READ_BUFFER_SIZE]; private static final char[] WRITE_BUFFER = new char[READ_BUFFER_SIZE]; private static final char[] BIB_REF_BUFFER = new char[BIB_REF_BUFFER_SIZE]; private static final int DIGITAL_MIN_VALUE = 0x30; public void order(InputStream in, OutputStream out) { try { Reader reader = new BufferedReader(new InputStreamReader(new BufferedInputStream(in))); Writer writer = new BufferedWriter(new OutputStreamWriter(new BufferedOutputStream(out))); List list = new LinkedList(); int charsRead; char actChar; int charsWritten = 0; int bibRefWritten = -1; int footnoteIndex = 0; while ((charsRead = reader.read(READ_BUFFER)) >= 0) { for (int j = 0; j < charsRead; j++) { actChar = (char) READ_BUFFER[j]; //beginning of the text, footnote not found yet if (footnoteIndex < FOOTNOTE.length) { footnoteIndex = (actChar == FOOTNOTE[footnoteIndex]) ? ++footnoteIndex : 0; WRITE_BUFFER[charsWritten++] = actChar; if (charsWritten >= WRITE_BUFFER_SIZE) { writer.write(WRITE_BUFFER); charsWritten = 0; } } else {//end of the text if (charsWritten != 0) { writer.write(WRITE_BUFFER); charsWritten = 0; } if (actChar == '[') { if (bibRefWritten == -1) {//indicates the first occurrence of '[' bibRefWritten = 0; } else { char[] text = Arrays.copyOfRange(BIB_REF_BUFFER, 0, bibRefWritten); list.add(new BibRefEntry(text)); bibRefWritten = 0; } } if (bibRefWritten != -1) { BIB_REF_BUFFER[bibRefWritten++] = actChar; } } } } //sorting the list can probably optimized too Collections.sort(list); for (BibRefEntry bibRefEntry : list) { writer.write(bibRefEntry.text); } } catch (IOException ex) { Logger.getLogger(OrderBibRef.class.getName()).log(Level.SEVERE, null, ex); } } private static class BibRefEntry implements Comparable { private final int tag; private final char[] text; public BibRefEntry(char[] text) { //Integer parse is too slow int tagLength = 1; while (text[tagLength] != ']') { tagLength++; } tagLength--; int tagLength2 = tagLength - 1; int t = 0; int pos = 0; for (int i = 0; i < tagLength; i++) { if (i != tagLength2) { pos = (int) Math.pow(10, tagLength2 - i); t += (text[i + 1] - DIGITAL_MIN_VALUE) * pos; } else { t += (text[i + 1] - DIGITAL_MIN_VALUE); } } this.tag = t; this.text = text; } public int compareTo(BibRefEntry o) { return tag - o.tag; } @Override public String toString() { return "tag: " + tag + " text: " + new String(text); } } }