/*
 * Copyright 2017 Philip Fritzsche <p-f@users.noreply.github.com>.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package one.p_f.testing.msagimport.grouping.io.dot;

import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import org.gradoop.common.model.impl.pojo.Edge;
import org.gradoop.common.model.impl.pojo.Vertex;
import org.gradoop.common.model.impl.properties.Property;
import org.gradoop.flink.io.impl.dot.functions.DOTFileFormat;
import org.gradoop.flink.representation.transactional.GraphTransaction;

/**
 * Improve the {@link DOTFileFormat} to produce valid and nicer DOT output.
 *
 * @author p-f
 * @see one.p_f.testing.msagimport.grouping.io.dot.ImprovedDotDataSink
 */
public class ImprovedDotFileFormat extends DOTFileFormat {

    private static final char NL = '\n';

    private static final char ATTR_PREFIX = 'a';

    private static final char NODE_PREFIX = 'v';

    public ImprovedDotFileFormat() {
        super(false);
    }

    @Override
    public String format(GraphTransaction transaction) {
        StringBuilder dot = new StringBuilder().append("digraph ")
                .append('g')
                .append(transaction.getGraphHead().getId())
                .append(" {\n");
        writeVertices(transaction, dot);
        writeEdges(transaction, dot);
        dot.append(NL).append('}');
        return dot.toString();
    }

    private static void writeEdges(GraphTransaction tr, StringBuilder sb) {
        for (Edge e : tr.getEdges()) {
            String from = String.format("%c%s", NODE_PREFIX,
                    e.getSourceId().toString());
            String to = String.format("%c%s", NODE_PREFIX,
                    e.getTargetId().toString());
            Stream<Property> propStream = e.getProperties() == null
                    ? Stream.of()
                    : StreamSupport
                            .stream(e.getProperties().spliterator(), false);
            String prop = propStream
                    .map(f -> f.getKey() + " = " + f.getValue())
                    .collect(Collectors.joining("\\n", "\"", "\""));
            sb.append(String.format("%s%s [label=%s,shape=\"Msquare\"];%c",
                    from, to, prop, NL));
            sb.append(String.format("%s -> %s;%c", from, from + to, NL));
            sb.append(String.format("%s -> %s;%c", from + to, to, NL));
        }
    }

    private static void writeVertices(GraphTransaction tr, StringBuilder sb) {
        for (Vertex v : tr.getVertices()) {
            String id = v.getId().toString();
            // Write vertex.
            sb.append(String.format("%c%s [label=\"%s\", shape=\"ellipse\"];%c",
                    NODE_PREFIX, id, v.getLabel(), NL));
            if (v.getProperties() == null) {
                continue;
            }
            for (Property p : v.getProperties()) {
                // Format property key.
                String propKey = p.getKey().replaceAll("\\s+", "_");
                String attrName = String.format("%c%s%c%s", NODE_PREFIX,
                        id, ATTR_PREFIX, propKey);
                // Write property.
                sb.append(String
                        .format("%s [label=\"%s = %s\", shape=\"rect\"];%c",
                                attrName, propKey, p.getValue(), NL));
                // Add edge vertex->property.
                sb.append(String.format("%c%s -> %s;%c", NODE_PREFIX, id,
                        attrName, NL));
            }
        }
    }
}

@@ -1398,24 +1398,78 @@
 FIX = 'a';%0A%0A
+    private static final String ATTR_SHAPE = %22rect%22;%0A%0A
     private 
@@ -1505,16 +1505,16 @@
  = 'v';%0A
-
 %0A    pub
@@ -2614,18 +2614,17 @@
 ey() + %22
- =
+:
  %22 + f.g
@@ -2767,15 +2767,10 @@
 e=%5C%22
-Msquare
+%25s
 %5C%22%5D;
@@ -2809,16 +2809,28 @@
 o, prop,
+ ATTR_SHAPE,
  NL));%0A 
@@ -3343,12 +3343,38 @@
     
-if (
+Stream%3CProperty%3E propStream = 
 v.ge
@@ -3394,19 +3394,16 @@
  == null
-) %7B
 %0A       
@@ -3415,448 +3415,374 @@
     
-continue;%0A            %7D%0A            for (Property p : v.getProperties()) %7B%0A                // Format property key.%0A                String propKey = p.getKey().replaceAll(%22%5C%5Cs+%22, %22_%22);%0A                String attrName = String.format(%22%25c%25s%25c%25s%22, NODE_PREFIX,%0A                        id, ATTR_PREFIX, propKey);%0A                // Write property.%0A                sb.append(String%0A                        .format(%22%25s %5Blabel=%5C%22%25s = %25s%5C%22, 
+    ? Stream.of()%0A                    : StreamSupport%0A                            .stream(v.getProperties().spliterator(), false);%0A            String prop = propStream%0A                    .map(f -%3E f.getKey() + %22: %22 + f.getValue())%0A                    .collect(Collectors.joining(%22%5C%5Cn%22, %22%5C%22%22, %22%5C%22%22));%0A            sb.append(String.format(%22%25c%25s_attr %5Blabel=%25s,
 shape=%5C%22
 rect
@@ -3777,20 +3777,18 @@
 shape=%5C%22
-rect
+%25s
 %5C%22%5D;%25c%22,
@@ -3812,109 +3812,49 @@
     
-            attrName, propKey, p.getValue(), NL));%0A                // Add edge vertex-%3Eproperty.%0A    
+NODE_PREFIX, id, prop, ATTR_SHAPE, NL));%0A
     
@@ -3891,25 +3891,32 @@
 t(%22%25c%25s -%3E %25
-s
+c%25s_attr
 ;%25c%22, NODE_P
@@ -3950,41 +3950,30 @@
     
-    attrName, NL));%0A            %7D
+NODE_PREFIX, id, NL));
 %0A   

Change attribute node style