//CHECKSTYLE:OFF
package com.tyndalehouse.step.tools.nave;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import com.tyndalehouse.step.core.utils.IOUtils;
import com.tyndalehouse.step.core.utils.StringUtils;
/**
* transforming the nave's file
*
* @author chrisburrell
*
*/
@SuppressWarnings("unused")
public class NaveTransforming {
public static void main(final String[] args) throws IOException {
new NaveTransforming("C:\\Users\\Chris\\Desktop\\nave-tyndale.txt");
}
final Map<String, Tree<String>> trees;
public NaveTransforming(final String source) throws IOException {
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader(source));
String line = br.readLine();
Tree<String> root = null;
final Map<String, Tree<String>> trees = new LinkedHashMap<String, Tree<String>>();
int indentation = 0;
final List<IndentedTree> parents = new ArrayList<IndentedTree>();
Tree<String> lastChild = null;
int ignoreIndent = 256;
while ((line = br.readLine()) != null) {
if (line.startsWith("$$")) {
continue;
}
final String trimmedLine = line.trim();
if (trimmedLine.length() == 0) {
continue;
}
final char c = trimmedLine.charAt(0);
if (c == '#') {
// count number of spaces
final int numberOfSpaces = line.indexOf('#');
String ref = trimmedLine.substring(1);
if (ref.charAt(ref.length() - 1) == '|') {
ref = ref.substring(0, ref.length() - 1);
}
lastChild.attachReference(ref);
ignoreIndent = numberOfSpaces;
continue;
}
if (c == '\\') {
ignoreIndent = 256;
if (root != null) {
// store root against its name
trees.put(parents.get(0).t.root, parents.get(0).t);
}
final String entryName = trimmedLine.substring(1, trimmedLine.length() - 1);
root = new Tree<String>(entryName);
lastChild = root;
indentation = 0;
parents.clear();
parents.add(new IndentedTree(root, 0));
continue;
}
if (c == '.' || c == '-') {
// count number of spaces...
int ii = 0;
while (line.charAt(ii) == ' ') {
ii++;
}
if (indentation == ii) {
lastChild = root.addChild(trimmedLine.substring(1));
} else if (ii > indentation) {
// we're going up a level, so add parent to stack
parents.add(new IndentedTree(lastChild, indentation));
root = lastChild;
lastChild = root.addChild(trimmedLine.substring(1));
} else {
// we're coming back down
while (parents.size() > 0) {
if (parents.get(parents.size() - 1).indent >= ii) {
// remove because we're not as indented or indented the same
parents.remove(parents.size() - 1);
} else {
// we break because we've reached a point where the list contains our
// immediate
// parent
break;
}
// else keep going...
} // end while
// so we've now got the parent at the same level, but we're interested in the level
// before...
root = parents.get(parents.size() - 1).t;
lastChild = root.addChild(trimmedLine.substring(1));
}
indentation = ii;
ignoreIndent = 256;
continue;
} else if (numSpaces(line) == ignoreIndent) {
// attach references
String ref = trimmedLine;
if (ref.charAt(ref.length() - 1) == '|') {
ref = ref.substring(0, ref.length() - 1);
}
lastChild.attachReference(ref);
continue;
} else {
// it's most likely a header that has been chopped:
lastChild.root = lastChild.root + ' ' + trimmedLine;
continue;
}
}
// do the last entry
trees.put(parents.get(0).t.root, parents.get(0).t);
// final print trees
final Set<Entry<String, Tree<String>>> printSet = trees.entrySet();
for (final Entry<String, Tree<String>> tree : printSet) {
// System.out.println(tree.getKey());
tree.getValue().print();
}
this.trees = trees;
// // create a map of the first and last entry
// final Map<String, Map<String, List<Tree<String>>>> firstAndLast = new LinkedHashMap<String,
// Map<String, List<Tree<String>>>>();
// final Set<Entry<String, Tree<String>>> entrySet = trees.entrySet();
// for (final Entry<String, Tree<String>> tree : entrySet) {
// addLastChildren(firstAndLast, tree.getValue(), tree.getKey().toLowerCase());
// }
// now we can try and match it against the output file
// matchFiles(firstAndLast);
} finally {
IOUtils.closeQuietly(br);
}
}
/**
* @param firstAndLast
*/
private void matchFiles(final Map<String, Map<String, List<Tree<String>>>> firstAndLast)
throws IOException {
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader("d:\\temp\\nave.txt"));
// read an entry:
Nave n;
int errors = 0;
while ((n = readEntry(br)) != null) {
if (StringUtils.isBlank(n.references)) {
continue;
}
final Map<String, List<Tree<String>>> map = firstAndLast.get(n.level0.toLowerCase());
if (map == null) {
errors++;
System.err.println("Can't find " + n.level0);
continue;
}
final List<Tree<String>> matchedEntry = map.get(n.lastHeading.toLowerCase());
if (matchedEntry == null) {
errors++;
System.err.println("Can't find last level heading: " + n.highestLevel);
continue;
}
matchesAnyLine(matchedEntry, n);
// now write nave to file
}
System.out.println("Number of errors " + errors);
} finally {
IOUtils.closeQuietly(br);
}
}
private boolean matchesAnyLine(final List<Tree<String>> matchedEntry, final Nave n) {
if (matchedEntry.size() == 1) {
// then it's bound to be this, so just make the change...
// so we found something, so rewrite the headings of the tree...
final StringBuilder sb = new StringBuilder(128);
getLongName(sb, matchedEntry.get(0));
final String shouldBeName = sb.toString();
if (!shouldBeName.equals(n.highestLevel)) {
System.out.println("Was " + n.highestLevel + ", now is " + shouldBeName);
n.highestLevel = shouldBeName;
}
return true;
}
// otherwise, we need to try all entries
for (final Tree<String> ent : matchedEntry) {
final StringBuilder sb = new StringBuilder(128);
getLongName(sb, matchedEntry.get(0));
final String shouldBeName = sb.toString();
if (shouldBeName.equals(sb.toString())) {
// no change required, as matched
return true;
}
}
// if we're still here, then we need to warn, as multiple entries match, and can't decide which one it
// might be...
System.err.println("Unable to match entry: " + n.lastHeading);
return false;
}
private void getLongName(final StringBuilder sb, final Tree<String> matchedEntry) {
if (matchedEntry.parentTree != null) {
getLongName(sb, matchedEntry.parentTree);
}
if (sb.length() > 0) {
sb.append(" - ");
}
sb.append(matchedEntry.root);
}
class Nave {
String level0;
String highestLevel;
String references;
String lastHeading;
}
private Nave readEntry(final BufferedReader br) throws IOException {
try {
final Nave n = new Nave();
while (readLine(n, br.readLine())) {
;
}
return n;
} catch (final RuntimeException e) {
// abort
return null;
}
}
private boolean readLine(final Nave n, final String line) {
if (line == null) {
throw new RuntimeException("abort");
}
if (line.startsWith("@HeadingLevel0")) {
n.level0 = line.substring(line.indexOf('\t') + 1);
} else if (line.startsWith("@HeadingLevel0")) {
} else if (line.startsWith("@HeadingLevel")) {
n.highestLevel = line.substring(line.indexOf('\t') + 1);
} else if (line.startsWith("@ReferenceLevel")) {
n.references = line.substring(line.indexOf('\t') + 1);
} else if (line.startsWith("@LastHeading")) {
n.lastHeading = line.substring(line.indexOf('\t') + 1);
} else if (line.startsWith("=======")) {
return false;
}
return true;
}
private int numSpaces(final String line) {
int spaces = 0;
while (line.charAt(spaces) == ' ') {
spaces++;
}
return spaces;
}
}