package net.rubygrapefruit.docs.model.buildable;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import net.rubygrapefruit.docs.model.Action;
import net.rubygrapefruit.docs.model.Document;
import java.util.HashMap;
import java.util.Map;
public class BuildableDocument extends BuildableComponent implements Document {
public String getTypeName() {
return "Book";
}
/**
* Finishes building this document. Does the following:
*
* <ul>
* <li>Assigns ids to those components with no id assigned already.
* <li>Resolves links and cross references.
* </ul>
*/
public void finish() {
assignIds();
super.finish();
}
private void assignIds() {
final Multimap<String, BuildableComponent> unassigned = HashMultimap.create();
final Map<String, BuildableComponent> assigned = new HashMap<String, BuildableComponent>();
final Map<String, Integer> typeCounts = new HashMap<String, Integer>();
visitAllComponents(new Action<BuildableComponent>() {
public void execute(BuildableComponent component) {
String type = component.getTypeName();
Integer value = typeCounts.get(type);
if (value == null) {
value = 1;
}
typeCounts.put(type, value + 1);
if (component.getId() != null && !component.getId().isEmpty()) {
assigned.put(component.getId(), component);
return;
}
String candidateId = component.getTitle().getText();
if (candidateId.isEmpty()) {
candidateId = type + value;
}
String id = candidateId.toLowerCase().replaceAll("\\s+", "_");
unassigned.put(id, component);
}
});
for (Map.Entry<String, BuildableComponent> entry : unassigned.entries()) {
BuildableComponent component = entry.getValue();
String id = entry.getKey();
if (!assigned.containsKey(id)) {
component.setId(id);
assigned.put(id, component);
continue;
}
for (int i = 1; ; i++) {
String candidate = id + '_' + i;
if (!assigned.containsKey(candidate)) {
assigned.put(candidate, component);
component.setId(candidate);
break;
}
}
}
}
}