/*******************************************************************************
* Copyright (c) 2016 itemis AG and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Fabian Steeg (hbz) - initial API and implementation
* Tamas Miklossy (itemis AG) - convert the DotExtractor to a top-level class (bug #508579)
*
*******************************************************************************/
package org.eclipse.gef.dot.internal;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* The DotExtractor is responsible for extracting the dot graph definitions from
* arbitrary text files.
*/
public class DotExtractor {
/**
* The DOT graph returned if the input contains no DOT graph substring.
*/
private final String NO_DOT = "graph{n1[label=\"no DOT\"]}"; //$NON-NLS-1$
private String input = NO_DOT;
/**
* @param input
* The string to extract a DOT graph substring from
*/
public DotExtractor(final String input) {
this.input = input;
}
/**
* @param file
* The file to extract a DOT substring from
*/
public DotExtractor(final File file) {
this(DotFileUtils.read(file));
}
/**
* @return A DOT string extracted from the input, or the {@code NO_DOT}
* constant, a valid DOT graph
*/
public String getDotString() {
return trimNonDotSuffix(trimNonDotPrefix());
}
/**
* @return A temporary file containing the DOT string extracted from the
* input, or the {@code NO_DOT} constant, a valid DOT graph
*/
public File getDotTempFile() {
File tempFile = null;
try {
tempFile = File.createTempFile("tempDotExtractorFile", ".dot"); //$NON-NLS-1$ //$NON-NLS-2$
} catch (IOException e) {
System.err.println("DotExtractor failed to create temp dot file"); //$NON-NLS-1$
e.printStackTrace();
}
if (tempFile != null) {
// use try-with-resources to utilize the AutoClosable
// functionality
try (BufferedWriter bw = new BufferedWriter(
new FileWriter(tempFile))) {
bw.write(getDotString());
} catch (IOException e) {
e.printStackTrace();
}
}
return tempFile;
}
private String trimNonDotPrefix() {
Matcher m = Pattern.compile("((?:di)?graph\\s*[^{\\s]*\\s*\\{.+)", //$NON-NLS-1$
Pattern.DOTALL).matcher(input);
String dotSubstring = m.find() ? m.group(1) : NO_DOT;
return dotSubstring;
}
private String trimNonDotSuffix(String dot) {
int first = dot.indexOf('{') + 1;
StringBuilder builder = new StringBuilder(dot.substring(0, first));
int count = 1; /* we count to include embedded { ... } blocks */
int index = first;
while (count > 0 && index < dot.length()) {
char c = dot.charAt(index);
builder.append(c);
count = (c == '{') ? count + 1 : (c == '}') ? count - 1 : count;
index++;
}
return builder.toString().trim();
}
}