package nl.knaw.huygens.alexandria.textgraph; /* * #%L * alexandria-main * ======= * Copyright (C) 2015 - 2017 Huygens ING (KNAW) * ======= * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program. If not, see * <http://www.gnu.org/licenses/gpl-3.0.html>. * #L% */ import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Stack; import java.util.UUID; import java.util.concurrent.atomic.AtomicInteger; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; import nl.knaw.huygens.alexandria.service.AlexandriaService; public class DotFactory { public static String createDot(AlexandriaService service, UUID resourceId) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("digraph TextGraph {\n")// .append(" ranksep=1.0\n\n"); AtomicInteger textCounter = new AtomicInteger(0); AtomicInteger annotationCounter = new AtomicInteger(0); Stack<Integer> openAnnotations = new Stack<>(); Multimap<Integer, Integer> annotationDepthMap = ArrayListMultimap.create(); service.runInTransaction(() -> service.getTextGraphSegmentStream(resourceId, new ArrayList<List<String>>()).forEach((s) -> { int tn = textCounter.getAndIncrement(); appendTextVertex(stringBuilder, s.getTextSegment(), tn); if (tn > 0) { appendNextTextEdge(stringBuilder, tn); } List<TextAnnotation> textAnnotationsToOpen = s.getTextAnnotationsToOpen(); s.getMilestoneTextAnnotation().ifPresent(textAnnotationsToOpen::add); for (TextAnnotation textAnnotation : textAnnotationsToOpen) { int an = annotationCounter.getAndIncrement(); appendAnnotationVertex(stringBuilder, an, textAnnotation); appendParentAnnotationEdge(stringBuilder, an, openAnnotations); annotationDepthMap.put(openAnnotations.size(), an); openAnnotations.push(an); } appendAnnotationEdge(stringBuilder, tn, openAnnotations.peek()); int numberOftextAnnotationsToClose = s.getTextAnnotationsToClose().size(); if (s.getMilestoneTextAnnotation().isPresent()) { numberOftextAnnotationsToClose += 1; } for (int i = 0; i < numberOftextAnnotationsToClose; i++) { if (!openAnnotations.isEmpty()) { openAnnotations.pop(); } } stringBuilder.append("\n"); })); appendTextHasSameRank(stringBuilder, textCounter.get()); for (Collection<Integer> values : annotationDepthMap.asMap().values()) { appendAnnotationsWithSameRank(stringBuilder, values); } stringBuilder.append("}"); return stringBuilder.toString(); } private static void appendTextVertex(StringBuilder stringBuilder, String textSegment, int n) { stringBuilder.append(" t")// .append(n)// .append(" [shape=box, label=\"")// .append(escape(textSegment)// .replace(" ", "␣")// .replace("\n", "↵"))// .append("\"];\n"); } private static String escape(String textSegment) { return textSegment.replace("\"", "\\\""); } private static void appendNextTextEdge(StringBuilder stringBuilder, int n) { stringBuilder.append(" t").append(n - 1).append(" -> t").append(n).append(";\n"); } private static void appendAnnotationVertex(StringBuilder stringBuilder, int an, TextAnnotation textAnnotation) { stringBuilder.append(" a")// .append(an)// .append(" [label=\"")// .append(escape(textAnnotation.getName()))// // .append(" (" + textAnnotation.getDepth() + ")")// .append("\"];\n"); } private static void appendParentAnnotationEdge(StringBuilder stringBuilder, int an, Stack<Integer> parents) { if (!parents.isEmpty()) { Integer parent = parents.peek(); stringBuilder.append(" a").append(parent).append(" -> a").append(an).append(";\n"); } } private static void appendAnnotationEdge(StringBuilder stringBuilder, int tn, Integer an) { stringBuilder.append(" a").append(an).append(" -> t").append(tn).append(" [color=\"blue\"];\n"); } private static void appendTextHasSameRank(StringBuilder stringBuilder, int size) { stringBuilder.append(" {rank=same;"); for (int i = 0; i < size; i++) { stringBuilder.append("t").append(i).append(";"); } stringBuilder.append("}\n"); } private static void appendAnnotationsWithSameRank(StringBuilder stringBuilder, Collection<Integer> annotations) { stringBuilder.append(" {rank=same;"); for (int annotation : annotations) { stringBuilder.append("a").append(annotation).append(";"); } stringBuilder.append("}\n"); } }