Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
View | Details | Raw Unified | Return to bug 491261
Collapse All | Expand All

(-)a/org.eclipse.gef4.dot.tests/src/org/eclipse/gef4/dot/tests/AllTests.java (-2 / +3 lines)
Lines 8-13 Link Here
8
 *
8
 *
9
 * Contributors:
9
 * Contributors:
10
 *     Alexander Nyßen (itemis AG) - initial API and implementation
10
 *     Alexander Nyßen (itemis AG) - initial API and implementation
11
 *     Tamas Miklossy  (itemis AG) - merge DotInterpreter into DotImport (bug #491261)
11
 *
12
 *
12
 *******************************************************************************/
13
 *******************************************************************************/
13
package org.eclipse.gef4.dot.tests;
14
package org.eclipse.gef4.dot.tests;
Lines 18-25 Link Here
18
19
19
@RunWith(Suite.class)
20
@RunWith(Suite.class)
20
@SuiteClasses({ DotImportTests.class, DotExportTests.class,
21
@SuiteClasses({ DotImportTests.class, DotExportTests.class,
21
		DotExecutableUtilsTests.class, DotInterpreterTests.class,
22
		DotExecutableUtilsTests.class, DotExtractorTests.class,
22
		DotExtractorTests.class, DotAttributesTests.class, DotParserTests.class,
23
		DotAttributesTests.class, DotParserTests.class,
23
		DotValidatorTests.class })
24
		DotValidatorTests.class })
24
public class AllTests {
25
public class AllTests {
25
26
(-)a/org.eclipse.gef4.dot.tests/src/org/eclipse/gef4/dot/tests/DotImportTests.java (-6 / +286 lines)
Lines 9-24 Link Here
9
 * Contributors:
9
 * Contributors:
10
 *     Fabian Steeg - initial API and implementation (see bug #277380)
10
 *     Fabian Steeg - initial API and implementation (see bug #277380)
11
 *     Tamas Miklossy  (itemis AG) - implement additional test cases (bug #493136)
11
 *     Tamas Miklossy  (itemis AG) - implement additional test cases (bug #493136)
12
 *                                 - merge DotInterpreter into DotImport (bug #491261)
12
 *
13
 *
13
 *******************************************************************************/
14
 *******************************************************************************/
14
package org.eclipse.gef4.dot.tests;
15
package org.eclipse.gef4.dot.tests;
15
16
16
import static org.eclipse.gef4.dot.tests.DotTestUtils.RESOURCES_TESTS;
17
import static org.eclipse.gef4.dot.tests.DotTestUtils.RESOURCES_TESTS;
18
import static org.junit.Assert.assertEquals;
17
19
18
import java.io.File;
20
import java.io.File;
21
import java.util.List;
19
22
20
import org.eclipse.gef4.dot.internal.DotAttributes;
23
import org.eclipse.gef4.dot.internal.DotAttributes;
21
import org.eclipse.gef4.dot.internal.DotImport;
24
import org.eclipse.gef4.dot.internal.DotImport;
25
import org.eclipse.gef4.dot.internal.parser.layout.Layout;
26
import org.eclipse.gef4.dot.internal.parser.rankdir.Rankdir;
22
import org.eclipse.gef4.graph.Edge;
27
import org.eclipse.gef4.graph.Edge;
23
import org.eclipse.gef4.graph.Graph;
28
import org.eclipse.gef4.graph.Graph;
24
import org.eclipse.gef4.graph.Node;
29
import org.eclipse.gef4.graph.Node;
Lines 30-44 Link Here
30
 * 
35
 * 
31
 * @author Fabian Steeg (fsteeg)
36
 * @author Fabian Steeg (fsteeg)
32
 */
37
 */
33
// TODO: this could be combined with the DotInterpreterTests, similar
34
// as DotExportTests and DotTemplateTests
35
public final class DotImportTests {
38
public final class DotImportTests {
39
40
	private final DotImport dotImport = new DotImport();
36
41
37
	private Graph testFileImport(final File dotFile) {
42
	private Graph testFileImport(final File dotFile) {
38
		Assert.assertTrue("DOT input file must exist: " + dotFile, //$NON-NLS-1$
43
		Assert.assertTrue("DOT input file must exist: " + dotFile, //$NON-NLS-1$
39
				dotFile.exists());
44
				dotFile.exists());
40
		Graph graph = new DotImport().importDot(dotFile);
45
		Graph graph = dotImport.importDot(dotFile);
41
		Assert.assertNotNull("Resulting graph must not be null", graph); //$NON-NLS-1$
46
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
42
		return graph;
47
		return graph;
43
	}
48
	}
44
49
Lines 85-91 Link Here
85
	 */
90
	 */
86
	@Test(expected = IllegalArgumentException.class)
91
	@Test(expected = IllegalArgumentException.class)
87
	public void invalidGraphFileImport() {
92
	public void invalidGraphFileImport() {
88
		new DotImport().importDot("graph Sample{");
93
		dotImport.importDot("graph Sample{");
94
	}
95
96
	@Test(expected = IllegalArgumentException.class)
97
	public void faultyLayout() {
98
		dotImport.importDot("graph Sample{graph[layout=cool];1;}"); //$NON-NLS-1$
99
	}
100
101
	@Test
102
	public void digraphType() {
103
		Graph graph = dotImport
104
				.importDot(DotTestGraphs.TWO_NODES_ONE_DIRECTED_EDGE);
105
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
106
		Assert.assertEquals(DotAttributes._TYPE__G__DIGRAPH,
107
				DotAttributes._getType(graph));
108
	}
109
110
	@Test
111
	public void graphType() {
112
		Graph graph = dotImport.importDot(DotTestGraphs.TWO_NODES_ONE_EDGE);
113
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
114
		Assert.assertEquals(DotAttributes._TYPE__G__GRAPH,
115
				DotAttributes._getType(graph));
116
	}
117
118
	@Test
119
	public void nodeDefaultLabel() {
120
		Graph graph = dotImport.importDot(DotTestGraphs.ONE_NODE);
121
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
122
		Assert.assertEquals("1", //$NON-NLS-1$
123
				DotAttributes._getName(graph.getNodes().get(0)));
124
	}
125
126
	@Test
127
	public void nodeCount() {
128
		Graph graph = dotImport.importDot(DotTestGraphs.TWO_NODES);
129
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
130
		Assert.assertEquals(2, graph.getNodes().size());
131
	}
132
133
	@Test
134
	public void edgeCount() {
135
		Graph graph = dotImport
136
				.importDot(DotTestGraphs.TWO_NODES_AND_THREE_EDGES);
137
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
138
		Assert.assertEquals(3, graph.getEdges().size());
139
	}
140
141
	@Test
142
	public void layoutSpring() {
143
		Graph graph = dotImport.importDot(DotTestGraphs.GRAPH_LAYOUT_FDP);
144
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
145
		Assert.assertEquals(Layout.FDP.toString(),
146
				DotAttributes.getLayout(graph));
147
	}
148
149
	@Test
150
	public void layoutGrid() {
151
		Graph graph = dotImport.importDot(DotTestGraphs.GRAPH_LAYOUT_OSAGE);
152
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
153
		Assert.assertEquals(Layout.OSAGE.toString(),
154
				DotAttributes.getLayout(graph));
155
	}
156
157
	@Test
158
	public void layoutRadial() {
159
		Graph graph = dotImport.importDot(DotTestGraphs.GRAPH_LAYOUT_TWOPI);
160
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
161
		Assert.assertEquals(Layout.TWOPI.toString(),
162
				DotAttributes.getLayout(graph));
163
	}
164
165
	@Test
166
	public void layoutTree() {
167
		Graph graph = dotImport.importDot(DotTestGraphs.GRAPH_LAYOUT_DOT);
168
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
169
		Assert.assertEquals(Layout.DOT.toString(),
170
				DotAttributes.getLayout(graph));
171
	}
172
173
	@Test
174
	public void layoutHorizontalTreeViaLayout() {
175
		Graph graph = dotImport
176
				.importDot(DotTestGraphs.GRAPH_LAYOUT_DOT_HORIZONTAL);
177
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
178
		Assert.assertEquals(Layout.DOT.toString(),
179
				DotAttributes.getLayout(graph));
180
		Assert.assertEquals(Rankdir.LR, DotAttributes.getRankdirParsed(graph));
181
	}
182
183
	@Test
184
	public void layoutHorizontalTreeViaAttribute() {
185
		Graph graph = dotImport.importDot(DotTestGraphs.GRAPH_RANKDIR_LR);
186
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
187
		Assert.assertEquals(Rankdir.LR, DotAttributes.getRankdirParsed(graph));
188
	}
189
190
	@Test
191
	public void globalNodeAttributeAdHocNodes() {
192
		Graph graph = dotImport
193
				.importDot(DotTestGraphs.GLOBAL_NODE_LABEL_AD_HOC_NODES);
194
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
195
		Assert.assertEquals("TEXT", //$NON-NLS-1$
196
				DotAttributes.getLabel(graph.getNodes().get(0)));
197
	}
198
199
	@Test
200
	public void globalEdgeAttributeAdHocNodes() {
201
		Graph graph = dotImport
202
				.importDot(DotTestGraphs.GLOBAL_EDGE_LABEL_AD_HOC_NODES);
203
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
204
		Assert.assertEquals("TEXT", DotAttributes.getLabel(graph.getEdges() //$NON-NLS-1$
205
				.get(0)));
206
	}
207
208
	@Test
209
	public void headerCommentGraph() {
210
		Graph graph = dotImport.importDot(DotTestGraphs.HEADER_COMMENT);
211
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
212
		Assert.assertEquals(2, graph.getNodes().size());
213
		Assert.assertEquals(1, graph.getEdges().size());
214
	}
215
216
	@Test
217
	public void nodesBeforeEdges() {
218
		Graph.Builder graph = new Graph.Builder().attr(DotAttributes._TYPE__G,
219
				DotAttributes._TYPE__G__GRAPH);
220
		Node[] nodes = createNodes();
221
		Edge e1 = new Edge.Builder(nodes[0], nodes[1])
222
				.attr(DotAttributes._NAME__GNE, "1--2") //$NON-NLS-1$
223
				.buildEdge();
224
		Edge e2 = new Edge.Builder(nodes[1], nodes[2])
225
				.attr(DotAttributes._NAME__GNE, "2--3") //$NON-NLS-1$
226
				.buildEdge();
227
		Edge e3 = new Edge.Builder(nodes[1], nodes[3])
228
				.attr(DotAttributes._NAME__GNE, "2--4") //$NON-NLS-1$
229
				.buildEdge();
230
		Graph expected = graph.nodes(nodes).edges(e1, e2, e3).build();
231
		testStringImport(expected, DotTestGraphs.NODES_BEFORE_EDGES);
232
	}
233
234
	@Test
235
	public void nodesAfterEdges() {
236
		Graph.Builder graph = new Graph.Builder().attr(DotAttributes._TYPE__G,
237
				DotAttributes._TYPE__G__GRAPH);
238
		Node[] nodes = createNodes();
239
		DotAttributes.setLabel(nodes[0], "node");
240
		Edge e1 = new Edge.Builder(nodes[0], nodes[1])
241
				.attr(DotAttributes._NAME__GNE, "1--2") //$NON-NLS-1$
242
				.buildEdge();
243
		Edge e2 = new Edge.Builder(nodes[1], nodes[2])
244
				.attr(DotAttributes._NAME__GNE, "2--3") //$NON-NLS-1$
245
				.buildEdge();
246
		Edge e3 = new Edge.Builder(nodes[1], nodes[3])
247
				.attr(DotAttributes._NAME__GNE, "2--4") //$NON-NLS-1$
248
				.buildEdge();
249
		Graph expected = graph.nodes(nodes).edges(e1, e2, e3).build();
250
		testStringImport(expected, DotTestGraphs.NODES_AFTER_EDGES);
251
	}
252
253
	@Test
254
	public void useDotImporterTwice() {
255
		String dot = DotTestGraphs.NODES_AFTER_EDGES;
256
		Graph graph = dotImport.importDot(dot);
257
		graph = dotImport.importDot(dot);
258
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
259
		Assert.assertEquals(4, graph.getNodes().size());
260
		Assert.assertEquals(3, graph.getEdges().size());
261
	}
262
263
	@Test
264
	public void idsWithQuotes() {
265
		Graph graph = dotImport.importDot(DotTestGraphs.IDS_WITH_QUOTES);
266
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
267
		List<Node> list = graph.getNodes();
268
		Assert.assertEquals("node 1", //$NON-NLS-1$
269
				DotAttributes._getName(list.get(0)));
270
		Assert.assertEquals("node 2", //$NON-NLS-1$
271
				DotAttributes._getName(list.get(1)));
272
	}
273
274
	@Test
275
	public void escapedQuotes() {
276
		Graph graph = dotImport.importDot(DotTestGraphs.ESCAPED_QUOTES_LABEL);
277
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
278
		Assert.assertEquals("node \"1\"", //$NON-NLS-1$
279
				DotAttributes.getLabel(graph.getNodes().get(0)));
280
	}
281
282
	@Test
283
	public void fullyQuoted() {
284
		Graph graph = dotImport.importDot(DotTestGraphs.FULLY_QUOTED_IDS);
285
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
286
		Assert.assertEquals(2, graph.getNodes().size());
287
		Assert.assertEquals(1, graph.getEdges().size());
288
		List<Node> list = graph.getNodes();
289
		Assert.assertEquals("n1", //$NON-NLS-1$
290
				DotAttributes._getName(list.get(0)));
291
		Assert.assertEquals("n2", //$NON-NLS-1$
292
				DotAttributes._getName(list.get(1)));
293
	}
294
295
	@Test
296
	public void labelsWithQuotes() {
297
		Graph graph = dotImport.importDot(DotTestGraphs.QUOTED_LABELS);
298
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
299
		List<Node> list = graph.getNodes();
300
		Assert.assertEquals("node 1", //$NON-NLS-1$
301
				DotAttributes.getLabel(list.get(0)));
302
		Assert.assertEquals("node 2", //$NON-NLS-1$
303
				DotAttributes.getLabel(list.get(1)));
304
		Assert.assertEquals("edge 1",
305
				DotAttributes.getLabel(graph.getEdges().get(0)));
306
	}
307
308
	@Test
309
	public void newLinesInLabels() {
310
		Graph graph = dotImport.importDot(DotTestGraphs.NEW_LINES_IN_LABELS);
311
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
312
		Assert.assertEquals("node" + System.lineSeparator() + "1", //$NON-NLS-1$
313
				DotAttributes.getLabel(graph.getNodes().get(0)));
314
	}
315
316
	@Test
317
	public void multiEdgeStatements() {
318
		// test global attribute
319
		Graph.Builder graph = new Graph.Builder().attr(DotAttributes._TYPE__G,
320
				DotAttributes._TYPE__G__DIGRAPH);
321
		Node[] nodes = createNodes();
322
		Edge e1 = new Edge.Builder(nodes[0], nodes[1])
323
				.attr(DotAttributes._NAME__GNE, "1->2") //$NON-NLS-1$
324
				.attr(DotAttributes.ARROWHEAD__E, "ornormal") //$NON-NLS-1$
325
				.buildEdge();
326
		Edge e2 = new Edge.Builder(nodes[1], nodes[2])
327
				.attr(DotAttributes._NAME__GNE, "2->3") //$NON-NLS-1$
328
				.attr(DotAttributes.ARROWHEAD__E, "ornormal") //$NON-NLS-1$
329
				.buildEdge();
330
		Edge e3 = new Edge.Builder(nodes[2], nodes[3])
331
				.attr(DotAttributes._NAME__GNE, "3->4") //$NON-NLS-1$
332
				.attr(DotAttributes.ARROWHEAD__E, "ornormal") //$NON-NLS-1$
333
				.buildEdge();
334
		Edge e4 = new Edge.Builder(nodes[0], nodes[1])
335
				.attr(DotAttributes._NAME__GNE, "1->2") //$NON-NLS-1$
336
				.attr(DotAttributes.ARROWHEAD__E, "ornormal") //$NON-NLS-1$
337
				.buildEdge();
338
		Edge e5 = new Edge.Builder(nodes[1], nodes[2])
339
				.attr(DotAttributes._NAME__GNE, "2->3") //$NON-NLS-1$
340
				.attr(DotAttributes.ARROWHEAD__E, "ornormal") //$NON-NLS-1$
341
				.buildEdge();
342
		Edge e6 = new Edge.Builder(nodes[2], nodes[3])
343
				.attr(DotAttributes._NAME__GNE, "3->4") //$NON-NLS-1$
344
				.attr(DotAttributes.ARROWHEAD__E, "ornormal") //$NON-NLS-1$
345
				.buildEdge();
346
		Graph expected = graph.nodes(nodes).edges(e1, e2, e3, e4, e5, e6)
347
				.build();
348
		testStringImport(expected, DotTestGraphs.MULTI_EDGE_STATEMENTS_GLOBAL);
349
350
		// test local attribute
351
		graph = new Graph.Builder().attr(DotAttributes._TYPE__G,
352
				DotAttributes._TYPE__G__DIGRAPH);
353
		DotAttributes.setArrowHead(e4, "olnormal");
354
		DotAttributes.setArrowHead(e5, "olnormal");
355
		DotAttributes.setArrowHead(e6, "olnormal");
356
		expected = graph.nodes(nodes).edges(e1, e2, e3, e4, e5, e6).build();
357
		testStringImport(expected, DotTestGraphs.MULTI_EDGE_STATEMENTS_LOCAL);
358
359
		// test override attribute
360
		testStringImport(expected,
361
				DotTestGraphs.MULTI_EDGE_STATEMENTS_OVERRIDE);
362
	}
363
364
	@Test
365
	public void edgeStyleInvis() {
366
		Graph graph = dotImport.importDot(DotTestGraphs.EDGE_STYLE_INVIS);
367
		assertEquals(2, graph.getNodes().size());
368
		assertEquals(1, graph.getEdges().size());
89
	}
369
	}
90
370
91
	@Test
371
	@Test
Lines 855-861 Link Here
855
	}
1135
	}
856
1136
857
	private void testStringImport(Graph expected, String dot) {
1137
	private void testStringImport(Graph expected, String dot) {
858
		Graph graph = new DotImport().importDot(dot);
1138
		Graph graph = dotImport.importDot(dot);
859
		Assert.assertNotNull("Resulting graph must not be null", graph); //$NON-NLS-1$
1139
		Assert.assertNotNull("Resulting graph must not be null", graph); //$NON-NLS-1$
860
		Assert.assertEquals(expected.toString(), graph.toString());
1140
		Assert.assertEquals(expected.toString(), graph.toString());
861
	}
1141
	}
(-)a/org.eclipse.gef4.dot.tests/src/org/eclipse/gef4/dot/tests/DotInterpreterTests.java (-366 lines)
Lines 1-366 Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009, 2016 itemis AG and others.
3
 *
4
 * All rights reserved. This program and the accompanying materials
5
 * are made available under the terms of the Eclipse Public License v1.0
6
 * which accompanies this distribution, and is available at
7
 * http://www.eclipse.org/legal/epl-v10.html
8
 *
9
 * Contributors:
10
 *     Fabian Steeg - initial API and implementation (see bug #277380)
11
 *     Tamas Miklossy (itemis AG) - Add support for all dot attributes (bug #461506)
12
 *
13
 *******************************************************************************/
14
package org.eclipse.gef4.dot.tests;
15
16
import static org.junit.Assert.assertEquals;
17
18
import java.io.StringReader;
19
import java.util.ArrayList;
20
import java.util.List;
21
22
import org.eclipse.gef4.dot.internal.DotAttributes;
23
import org.eclipse.gef4.dot.internal.DotImport;
24
import org.eclipse.gef4.dot.internal.DotInterpreter;
25
import org.eclipse.gef4.dot.internal.parser.DotStandaloneSetup;
26
import org.eclipse.gef4.dot.internal.parser.dot.DotAst;
27
import org.eclipse.gef4.dot.internal.parser.layout.Layout;
28
import org.eclipse.gef4.dot.internal.parser.parser.antlr.DotParser;
29
import org.eclipse.gef4.dot.internal.parser.rankdir.Rankdir;
30
import org.eclipse.gef4.dot.internal.parser.style.EdgeStyle;
31
import org.eclipse.gef4.graph.Edge;
32
import org.eclipse.gef4.graph.Graph;
33
import org.eclipse.gef4.graph.Node;
34
import org.junit.Assert;
35
import org.junit.Test;
36
37
import com.google.inject.Injector;
38
39
/**
40
 * Tests for dynamic import of DOT to a Zest graph instance.
41
 * 
42
 * @author Fabian Steeg (fsteeg)
43
 */
44
public final class DotInterpreterTests {
45
46
	private static final Injector dotInjector = new DotStandaloneSetup()
47
			.createInjectorAndDoEMFRegistration();
48
	private static final DotParser dotParser = dotInjector
49
			.getInstance(DotParser.class);
50
51
	private final DotInterpreter interpreter = new DotInterpreter();
52
53
	@Test
54
	public void digraphType() {
55
		Graph graph = interpreter
56
				.interpret(parse(DotTestGraphs.TWO_NODES_ONE_DIRECTED_EDGE))
57
				.get(0);
58
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
59
		Assert.assertEquals(DotAttributes._TYPE__G__DIGRAPH,
60
				DotAttributes._getType(graph));
61
	}
62
63
	@Test
64
	public void graphType() {
65
		Graph graph = interpreter
66
				.interpret(parse(DotTestGraphs.TWO_NODES_ONE_EDGE)).get(0);
67
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
68
		Assert.assertEquals(DotAttributes._TYPE__G__GRAPH,
69
				DotAttributes._getType(graph));
70
	}
71
72
	@Test
73
	public void nodeDefaultLabel() {
74
		Graph graph = interpreter.interpret(parse(DotTestGraphs.ONE_NODE))
75
				.get(0);
76
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
77
		Assert.assertEquals("1", //$NON-NLS-1$
78
				DotAttributes._getName(graph.getNodes().get(0)));
79
	}
80
81
	@Test
82
	public void nodeCount() {
83
		Graph graph = interpreter.interpret(parse(DotTestGraphs.TWO_NODES))
84
				.get(0);
85
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
86
		Assert.assertEquals(2, graph.getNodes().size());
87
	}
88
89
	@Test
90
	public void edgeCount() {
91
		Graph graph = interpreter
92
				.interpret(parse(DotTestGraphs.TWO_NODES_AND_THREE_EDGES))
93
				.get(0);
94
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
95
		Assert.assertEquals(3, graph.getEdges().size());
96
	}
97
98
	@Test
99
	public void nodeLabel() {
100
		Graph graph = interpreter
101
				.interpret(parse(DotTestGraphs.NODE_LABEL_LOCAL)).get(0);
102
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
103
		Assert.assertEquals("Node1", //$NON-NLS-1$
104
				DotAttributes.getLabel(graph.getNodes().get(0)));
105
	}
106
107
	@Test
108
	public void edgeLabel() {
109
		Graph graph = interpreter
110
				.interpret(parse(DotTestGraphs.EDGE_LABEL_LOCAL)).get(0);
111
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
112
		Assert.assertEquals("Edge1", DotAttributes.getLabel(graph.getEdges() //$NON-NLS-1$
113
				.get(0)));
114
	}
115
116
	@Test
117
	public void edgeStyle() {
118
		Graph graph = interpreter
119
				.interpret(parse(DotTestGraphs.EDGE_STYLE_LOCAL)).get(0);
120
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
121
		Assert.assertEquals(EdgeStyle.DASHED.toString(),
122
				DotAttributes.getStyle(graph.getEdges().get(0)));
123
	}
124
125
	@Test
126
	public void globalEdgeStyle() {
127
		Graph graph = interpreter
128
				.interpret(parse(DotTestGraphs.EDGE_STYLE_GLOBAL)).get(0);
129
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
130
		Assert.assertEquals(EdgeStyle.DASHED.toString(),
131
				DotAttributes.getStyle(graph.getEdges().get(0)));
132
	}
133
134
	@Test
135
	public void globalEdgeLabel() {
136
		Graph graph = interpreter
137
				.interpret(parse(DotTestGraphs.EDGE_LABEL_GLOBAL)).get(0);
138
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
139
		Assert.assertEquals("Edge1", DotAttributes.getLabel(graph.getEdges() //$NON-NLS-1$
140
				.get(0)));
141
	}
142
143
	@Test
144
	public void globalNodeLabel() {
145
		Graph graph = interpreter
146
				.interpret(parse(DotTestGraphs.NODE_LABEL_GLOBAL)).get(0);
147
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
148
		Assert.assertEquals("Node1", //$NON-NLS-1$
149
				DotAttributes.getLabel(graph.getNodes().get(0)));
150
	}
151
152
	@Test
153
	public void layoutSpring() {
154
		Graph graph = interpreter
155
				.interpret(parse(DotTestGraphs.GRAPH_LAYOUT_FDP)).get(0);
156
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
157
		Assert.assertEquals(Layout.FDP.toString(),
158
				DotAttributes.getLayout(graph));
159
	}
160
161
	@Test
162
	public void layoutGrid() {
163
		Graph graph = interpreter
164
				.interpret(parse(DotTestGraphs.GRAPH_LAYOUT_OSAGE)).get(0);
165
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
166
		Assert.assertEquals(Layout.OSAGE.toString(),
167
				DotAttributes.getLayout(graph));
168
	}
169
170
	@Test
171
	public void layoutRadial() {
172
		Graph graph = interpreter
173
				.interpret(parse(DotTestGraphs.GRAPH_LAYOUT_TWOPI)).get(0);
174
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
175
		Assert.assertEquals(Layout.TWOPI.toString(),
176
				DotAttributes.getLayout(graph));
177
	}
178
179
	@Test
180
	public void layoutTree() {
181
		Graph graph = interpreter
182
				.interpret(parse(DotTestGraphs.GRAPH_LAYOUT_DOT)).get(0);
183
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
184
		Assert.assertEquals(Layout.DOT.toString(),
185
				DotAttributes.getLayout(graph));
186
	}
187
188
	@Test
189
	public void layoutHorizontalTreeViaLayout() {
190
		Graph graph = interpreter
191
				.interpret(parse(DotTestGraphs.GRAPH_LAYOUT_DOT_HORIZONTAL))
192
				.get(0);
193
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
194
		Assert.assertEquals(Layout.DOT.toString(),
195
				DotAttributes.getLayout(graph));
196
		Assert.assertEquals(Rankdir.LR, DotAttributes.getRankdirParsed(graph));
197
	}
198
199
	@Test
200
	public void layoutHorizontalTreeViaAttribute() {
201
		Graph graph = interpreter
202
				.interpret(parse(DotTestGraphs.GRAPH_RANKDIR_LR)).get(0);
203
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
204
		Assert.assertEquals(Rankdir.LR, DotAttributes.getRankdirParsed(graph));
205
	}
206
207
	@Test
208
	public void globalNodeAttributeAdHocNodes() {
209
		Graph graph = interpreter
210
				.interpret(
211
						parse(DotTestGraphs.GLOBAL_NODE_LABEL_AD_HOC_NODES))
212
				.get(0);
213
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
214
		Assert.assertEquals("TEXT", //$NON-NLS-1$
215
				DotAttributes.getLabel(graph.getNodes().get(0)));
216
	}
217
218
	@Test
219
	public void globalEdgeAttributeAdHocNodes() {
220
		Graph graph = interpreter
221
				.interpret(
222
						parse(DotTestGraphs.GLOBAL_EDGE_LABEL_AD_HOC_NODES))
223
				.get(0);
224
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
225
		Assert.assertEquals("TEXT", DotAttributes.getLabel(graph.getEdges() //$NON-NLS-1$
226
				.get(0)));
227
	}
228
229
	@Test
230
	public void headerCommentGraph() {
231
		Graph graph = interpreter
232
				.interpret(parse(DotTestGraphs.HEADER_COMMENT)).get(0);
233
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
234
		Assert.assertEquals(2, graph.getNodes().size());
235
		Assert.assertEquals(1, graph.getEdges().size());
236
	}
237
238
	@Test
239
	public void nodesBeforeEdges() {
240
		Graph graph = interpreter
241
				.interpret(parse(DotTestGraphs.NODES_BEFORE_EDGES)).get(0);
242
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
243
		Assert.assertEquals(4, graph.getNodes().size());
244
		Assert.assertEquals(3, graph.getEdges().size());
245
	}
246
247
	@Test
248
	public void nodesAfterEdges() {
249
		Graph graph = interpreter
250
				.interpret(parse(DotTestGraphs.NODES_AFTER_EDGES)).get(0);
251
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
252
		Assert.assertEquals(4, graph.getNodes().size());
253
		Assert.assertEquals(3, graph.getEdges().size());
254
		Assert.assertEquals("node",
255
				DotAttributes.getLabel(graph.getNodes().get(0)));
256
	}
257
258
	@Test
259
	public void useInterpreterTwice() {
260
		String dot = DotTestGraphs.NODES_AFTER_EDGES;
261
		Graph graph = interpreter.interpret(parse(dot)).get(0);
262
		graph = interpreter.interpret(parse(dot)).get(0);
263
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
264
		Assert.assertEquals(4, graph.getNodes().size());
265
		Assert.assertEquals(3, graph.getEdges().size());
266
	}
267
268
	@Test
269
	public void idsWithQuotes() {
270
		Graph graph = interpreter
271
				.interpret(parse(DotTestGraphs.IDS_WITH_QUOTES)).get(0);
272
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
273
		List<Node> list = graph.getNodes();
274
		Assert.assertEquals("node 1", //$NON-NLS-1$
275
				DotAttributes._getName(list.get(0)));
276
		Assert.assertEquals("node 2", //$NON-NLS-1$
277
				DotAttributes._getName(list.get(1)));
278
	}
279
280
	@Test
281
	public void escapedQuotes() {
282
		Graph graph = interpreter
283
				.interpret(parse(DotTestGraphs.ESCAPED_QUOTES_LABEL)).get(0);
284
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
285
		Assert.assertEquals("node \"1\"", //$NON-NLS-1$
286
				DotAttributes.getLabel(graph.getNodes().get(0)));
287
	}
288
289
	@Test
290
	public void fullyQuoted() {
291
		Graph graph = interpreter
292
				.interpret(parse(DotTestGraphs.FULLY_QUOTED_IDS)).get(0);
293
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
294
		Assert.assertEquals(2, graph.getNodes().size());
295
		Assert.assertEquals(1, graph.getEdges().size());
296
		List<Node> list = graph.getNodes();
297
		Assert.assertEquals("n1", //$NON-NLS-1$
298
				DotAttributes._getName(list.get(0)));
299
		Assert.assertEquals("n2", //$NON-NLS-1$
300
				DotAttributes._getName(list.get(1)));
301
	}
302
303
	@Test
304
	public void labelsWithQuotes() {
305
		Graph graph = interpreter
306
				.interpret(parse(DotTestGraphs.QUOTED_LABELS)).get(0);
307
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
308
		List<Node> list = graph.getNodes();
309
		Assert.assertEquals("node 1", //$NON-NLS-1$
310
				DotAttributes.getLabel(list.get(0)));
311
		Assert.assertEquals("node 2", //$NON-NLS-1$
312
				DotAttributes.getLabel(list.get(1)));
313
		Assert.assertEquals("edge 1",
314
				DotAttributes.getLabel(graph.getEdges().get(0)));
315
	}
316
317
	@Test
318
	public void newLinesInLabels() {
319
		Graph graph = interpreter
320
				.interpret(parse(DotTestGraphs.NEW_LINES_IN_LABELS)).get(0);
321
		Assert.assertNotNull("Created graph must not be null", graph); //$NON-NLS-1$
322
		Assert.assertEquals("node" + System.lineSeparator() + "1", //$NON-NLS-1$
323
				DotAttributes.getLabel(graph.getNodes().get(0)));
324
	}
325
326
	@Test
327
	public void multiEdgeStatements() {
328
		Graph graph = new DotImport()
329
				.importDot(DotTestGraphs.MULTI_EDGE_STATEMENTS);
330
		assertEquals(4, graph.getNodes().size());
331
		assertEquals(3, graph.getEdges().size());
332
		/* Each node should be connected to one other, the previous node: */
333
		List<Node> list = graph.getNodes();
334
		assertEquals(1, getSourceConnections(list.get(1), graph).size());
335
		assertEquals(1, getSourceConnections(list.get(1), graph).size());
336
		assertEquals(1, getSourceConnections(list.get(1), graph).size());
337
	}
338
339
	private List<Edge> getSourceConnections(Node node, Graph graph) {
340
		List<Edge> result = new ArrayList<>();
341
		List<Edge> edges = graph.getEdges();
342
		for (Edge edge : edges)
343
			if (edge.getTarget().equals(node))
344
				result.add(edge);
345
		return result;
346
	}
347
348
	@Test
349
	/* see http://www.graphviz.org/doc/info/attrs.html#d:style */
350
	public void edgeStyleInvis() {
351
		Graph graph = new DotImport()
352
				.importDot(DotTestGraphs.EDGE_STYLE_INVIS);
353
		assertEquals(2, graph.getNodes().size());
354
		assertEquals(1, graph.getEdges().size());
355
	}
356
357
	@Test(expected = IllegalArgumentException.class)
358
	public void faultyLayout() {
359
		interpreter.interpret(parse("graph Sample{graph[layout=cool];1;}")); //$NON-NLS-1$
360
	}
361
362
	private DotAst parse(String dot) {
363
		return (DotAst) dotParser.parse(new StringReader(dot))
364
				.getRootASTElement();
365
	}
366
}
(-)a/org.eclipse.gef4.dot.tests/src/org/eclipse/gef4/dot/tests/DotTestGraphs.xtend (-1 / +17 lines)
Lines 171-182 Link Here
171
		}
171
		}
172
	'''
172
	'''
173
	
173
	
174
	public static val MULTI_EDGE_STATEMENTS = '''
174
	public static val MULTI_EDGE_STATEMENTS_GLOBAL = '''
175
		digraph {
175
		digraph {
176
			edge[arrowhead=ornormal]
177
			1->2->3->4
176
			1->2->3->4
178
			1->2->3->4
177
		}
179
		}
178
	'''
180
	'''
179
	
181
	
182
	public static val MULTI_EDGE_STATEMENTS_LOCAL = '''
183
		digraph {
184
			1->2->3->4[arrowhead=ornormal]
185
			1->2->3->4[arrowhead=olnormal]
186
		}
187
	'''
188
	
189
	public static val MULTI_EDGE_STATEMENTS_OVERRIDE = '''
190
		digraph {
191
			edge[arrowhead=olnormal]
192
			1->2->3->4[arrowhead=ornormal]
193
			1->2->3->4
194
		}
195
	'''	
180
	public static val NEW_LINES_IN_LABELS = '''
196
	public static val NEW_LINES_IN_LABELS = '''
181
		graph {
197
		graph {
182
			n1[label=
198
			n1[label=
(-)a/org.eclipse.gef4.dot/src/org/eclipse/gef4/dot/internal/DotImport.xtend (-5 / +302 lines)
Lines 7-12 Link Here
7
 * 
7
 * 
8
 * Contributors:
8
 * Contributors:
9
 *     Alexander Nyßen (itemis AG) - initial API and implementation
9
 *     Alexander Nyßen (itemis AG) - initial API and implementation
10
 *     Tamas Miklossy  (itemis AG) - merge DotInterpreter into DotImport (bug #491261)
10
 * 
11
 * 
11
 *******************************************************************************/
12
 *******************************************************************************/
12
package org.eclipse.gef4.dot.internal
13
package org.eclipse.gef4.dot.internal
Lines 14-23 Link Here
14
import com.google.inject.Injector
15
import com.google.inject.Injector
15
import java.io.File
16
import java.io.File
16
import java.io.StringReader
17
import java.io.StringReader
18
import java.util.List
19
import java.util.Map
17
import org.eclipse.gef4.dot.internal.parser.DotStandaloneSetup
20
import org.eclipse.gef4.dot.internal.parser.DotStandaloneSetup
21
import org.eclipse.gef4.dot.internal.parser.conversion.DotTerminalConverters
22
import org.eclipse.gef4.dot.internal.parser.dot.AttrList
23
import org.eclipse.gef4.dot.internal.parser.dot.AttrStmt
24
import org.eclipse.gef4.dot.internal.parser.dot.Attribute
18
import org.eclipse.gef4.dot.internal.parser.dot.DotAst
25
import org.eclipse.gef4.dot.internal.parser.dot.DotAst
26
import org.eclipse.gef4.dot.internal.parser.dot.DotGraph
27
import org.eclipse.gef4.dot.internal.parser.dot.EdgeRhs
28
import org.eclipse.gef4.dot.internal.parser.dot.EdgeRhsNode
29
import org.eclipse.gef4.dot.internal.parser.dot.EdgeRhsSubgraph
30
import org.eclipse.gef4.dot.internal.parser.dot.EdgeStmtNode
31
import org.eclipse.gef4.dot.internal.parser.dot.GraphType
32
import org.eclipse.gef4.dot.internal.parser.dot.NodeId
33
import org.eclipse.gef4.dot.internal.parser.dot.NodeStmt
34
import org.eclipse.gef4.dot.internal.parser.dot.Stmt
19
import org.eclipse.gef4.dot.internal.parser.parser.antlr.DotParser
35
import org.eclipse.gef4.dot.internal.parser.parser.antlr.DotParser
36
import org.eclipse.gef4.dot.internal.parser.splines.Splines
37
import org.eclipse.gef4.graph.Edge
20
import org.eclipse.gef4.graph.Graph
38
import org.eclipse.gef4.graph.Graph
39
import org.eclipse.gef4.graph.Graph.Builder
40
import org.eclipse.gef4.graph.Node
41
42
import static extension org.eclipse.gef4.dot.internal.DotAttributes.*
43
import org.eclipse.gef4.dot.internal.parser.dot.DotFactory
21
44
22
/**
45
/**
23
 * A parser that creates a {@link Graph} with {@link DotAttributes} from a Graphviz DOT string or file.
46
 * A parser that creates a {@link Graph} with {@link DotAttributes} from a Graphviz DOT string or file.
Lines 27-35 Link Here
27
 */
50
 */
28
class DotImport {
51
class DotImport {
29
52
30
	private static final Injector dotInjector = new DotStandaloneSetup().createInjectorAndDoEMFRegistration();
53
	// fields are private by default 
31
	private static final DotParser dotParser = dotInjector.getInstance(typeof(DotParser)) as DotParser;
54
	val static Injector dotInjector = new DotStandaloneSetup().createInjectorAndDoEMFRegistration
32
55
	val static DotParser dotParser = dotInjector.getInstance(DotParser)
56
	
57
	Builder graphBuilder
58
	Map<String, String> globalGraphAttributes = newHashMap
59
	Map<String, String> globalNodeAttributes = newHashMap
60
	Map<String, String> globalEdgeAttributes = newHashMap
61
	
33
	// TODO: support a list of graphs
62
	// TODO: support a list of graphs
34
	def Graph importDot(String dotString) {
63
	def Graph importDot(String dotString) {
35
		var parseResult = dotParser.parse(new StringReader(dotString))
64
		var parseResult = dotParser.parse(new StringReader(dotString))
Lines 41-52 Link Here
41
		}
70
		}
42
		// TODO: use validator to semantically validate as well
71
		// TODO: use validator to semantically validate as well
43
72
44
		// TODO: return list of graphs rather than first one
73
		// TODO: return list of graphs rather than only the first one
45
		new DotInterpreter().interpret(parseResult.rootASTElement as DotAst).head
74
		(parseResult.rootASTElement as DotAst).transformDotAst
46
	}
75
	}
47
76
48
	// TODO: support a list of graphs
77
	// TODO: support a list of graphs
49
	def Graph importDot(File dotFile) {
78
	def Graph importDot(File dotFile) {
50
		importDot(DotFileUtils.read(dotFile))
79
		importDot(DotFileUtils.read(dotFile))
51
	}
80
	}
81
82
    private def Graph transformDotAst(DotAst it){
83
		// TODO: return list of graphs rather than only the first one
84
		graphs.map[transformDotGraph].head
85
	}
86
	
87
	private def Graph transformDotGraph(DotGraph it){
88
		// clear global attributes, which only hold for each respective graph
89
		globalGraphAttributes.clear
90
		globalNodeAttributes.clear
91
		globalEdgeAttributes.clear
92
		
93
		// create a new graph builder and clear the nodes map
94
		graphBuilder = new Graph.Builder
95
		_createCache_createNode.clear
96
		
97
		// name (meta-attribute)
98
		val escapedName = name.escaped
99
		if (escapedName != null) {
100
			graphBuilder.attr(_NAME__GNE, escapedName)
101
		}
102
		
103
		// type (meta-attribute)
104
		graphBuilder.attr(_TYPE__G,
105
				if (type == GraphType.GRAPH) 
106
					_TYPE__G__GRAPH 
107
				else 
108
					_TYPE__G__DIGRAPH
109
		)
110
		
111
		// process all statements except for graph attributes, they will be processed later
112
		stmts.filter[!(it instanceof Attribute)].forEach[transformStmt]
113
		
114
		// process the graph last, so we can initialize attributes of the
115
		// created graph object rather than using the builder we can thus
116
		// ensure attribute values get properly validated.
117
		val graph = graphBuilder.build
118
		
119
		val setter = [
120
			String attributeName, (Graph, String)=>void f | 
121
			val attributeValue = getAttributeValue(attributeName)
122
			if (attributeValue != null) {
123
				f.apply(graph, attributeValue)
124
			} else if (globalGraphAttributes.containsKey(attributeName)) {
125
				f.apply(graph, globalGraphAttributes.get(attributeName))
126
			}
127
		]
128
		
129
		setter.apply(LAYOUT__G,  [g, value | g.setLayout(value) ])
130
		setter.apply(RANKDIR__G, [g, value | g.setRankdir(value)])
131
		
132
		// splines
133
		var splines = getAttributeValue(SPLINES__G)
134
		if (splines == null && globalGraphAttributes.containsKey(SPLINES__G)) {
135
			splines = globalGraphAttributes.get(SPLINES__G)
136
		}
137
		if (splines != null) {
138
			// XXX: splines can either be a defined enum value or a bool value
139
			// (which is mapped to respective enum values) we use the enum
140
			// values alone and thus map the bool value here
141
			val Boolean booleanValue = DotLanguageSupport.parseAttributeValue(
142
					DotLanguageSupport.BOOL_PARSER, splines)
143
			if (booleanValue != null) {
144
				graph.setSplinesParsed(
145
						if (Boolean.TRUE.equals(booleanValue))
146
							Splines.TRUE
147
						else 
148
							Splines.FALSE
149
					)
150
			} else {
151
				graph.setSplines(splines)
152
			}
153
		}		
154
		
155
		graph		
156
	}
157
	
158
	private def Node transformNodeId(NodeId it) {
159
		// create an empty attribute lists indicating no local node attribute definitions
160
		transformNodeId(#[DotFactory.eINSTANCE.createAttrList])
161
	}
162
	
163
	private def Node transformNodeId(NodeId it, List<AttrList> attrLists) {
164
		val node = name.escaped.createNode
165
	
166
		val setter = [
167
			String attributeName, (Node, String)=>void f | 
168
			val attributeValue = attrLists.getAttributeValue(attributeName)
169
			if (attributeValue != null) {
170
				f.apply(node, attributeValue)
171
			} else if (globalNodeAttributes.containsKey(attributeName)) {
172
				f.apply(node, globalNodeAttributes.get(attributeName))
173
			}
174
		]
175
		
176
		setter.apply(DISTORTION__N, [n, value | n.setDistortion(value)])
177
		setter.apply(FIXEDSIZE__N,  [n, value | n.setFixedSize(value) ])
178
		setter.apply(HEIGHT__N,     [n, value | n.setHeight(value)    ])
179
		setter.apply(ID__GNE,       [n, value | n.setId(value)        ])
180
		setter.apply(LABEL__GNE,    [n, value | n.setLabel(value)     ])
181
		setter.apply(POS__NE,   	[n, value | n.setPos(value)       ])
182
		setter.apply(SHAPE__N,   	[n, value | n.setShape(value)     ])
183
		setter.apply(SIDES__N,   	[n, value | n.setSides(value)     ])
184
		setter.apply(SKEW__N,   	[n, value | n.setSkew(value)      ])
185
		setter.apply(STYLE__GNE,   	[n, value | n.setStyle(value)     ])
186
		setter.apply(WIDTH__N,   	[n, value | n.setWidth(value)     ])
187
		setter.apply(XLABEL__NE,   	[n, value | n.setXLabel(value)    ])
188
		setter.apply(XLP__NE,   	[n, value | n.setXlp(value)       ])
189
		
190
		node
191
	}
192
	
193
	/*
194
	********************************************************************************************************************************
195
	*  dynamic dispatch methods 
196
	********************************************************************************************************************************
197
	*/		
198
	private def dispatch void transformStmt(Stmt it){
199
		throw new IllegalArgumentException("DotImport cannot transform statement: " + class)
200
	}
201
	
202
	private def dispatch void transformStmt(AttrStmt it) {
203
		switch type {
204
		case GRAPH: {
205
			// global graph attributes
206
			attrLists.forEach[
207
				attributes.forEach[
208
					globalGraphAttributes.put(name, value.escaped)
209
				]
210
			]
211
		}
212
		case NODE: {
213
			// global node attributes
214
			attrLists.forEach[
215
				attributes.forEach[
216
					globalNodeAttributes.put(name, value.escaped)
217
				]
218
			]
219
		}
220
		case EDGE: {
221
			// global edge attributes
222
			attrLists.forEach[
223
				attributes.forEach[
224
					globalEdgeAttributes.put(name, value.escaped)
225
				]
226
			]
227
		}
228
		}
229
	}
230
	
231
	private def dispatch void transformStmt(NodeStmt it){		
232
		node.transformNodeId(attrLists)
233
	}	
234
	
235
	private def dispatch void transformStmt(EdgeStmtNode it) {
236
		var sourceNode = node.transformNodeId
237
		for(EdgeRhs edgeRhs : edgeRHS){
238
			switch edgeRhs {
239
				EdgeRhsNode: {  
240
					val targetNode = edgeRhs.node.transformNodeId
241
					createEdge(sourceNode, edgeRhs.op.literal, targetNode, attrLists)
242
					// current target node may be source for next EdgeRHS
243
					sourceNode = targetNode
244
				}
245
				EdgeRhsSubgraph: {
246
					// TODO: add support for transforming edges with
247
					// subgraphs on their right hand side
248
				}
249
				default:{
250
					throw new IllegalArgumentException("DotImport cannot transform EdgeRhs: " + class)
251
				}
252
			}			
253
		}
254
	}
255
	
256
	private def create new Node.Builder().buildNode() createNode(String nodeName) {
257
		_setName(nodeName)
258
		graphBuilder.nodes(it)
259
	}
260
	
261
	def private void createEdge(Node sourceNode, String edgeOp, Node targetNode, List<AttrList> attrLists) {
262
		val edge = new Edge.Builder(sourceNode, targetNode)
263
				.attr(_NAME__GNE, sourceNode._getName + edgeOp + targetNode._getName)
264
				.buildEdge()
265
		
266
		val setter = [
267
			String attributeName, (Edge, String)=>void f | 
268
			val attributeValue = attrLists.getAttributeValue(attributeName)
269
			if (attributeValue != null) {
270
				f.apply(edge, attributeValue)
271
			} else if (globalEdgeAttributes.containsKey(attributeName)) {
272
				f.apply(edge, globalEdgeAttributes.get(attributeName))
273
			}
274
		]
275
		
276
		setter.apply(ARROWHEAD__E, [e, value | e.setArrowHead(value)])
277
		setter.apply(ARROWSIZE__E, [e, value | e.setArrowSize(value)])
278
		setter.apply(ARROWTAIL__E, [e, value | e.setArrowTail(value)])
279
		setter.apply(DIR__E,       [e, value | e.setDir(value)      ])
280
        setter.apply(HEAD_LP__E,   [e, value | e.setHeadLp(value)   ])
281
        setter.apply(HEADLABEL__E, [e, value | e.setHeadLabel(value)])
282
        setter.apply(ID__GNE,      [e, value | e.setId(value)       ])
283
        setter.apply(LABEL__GNE,   [e, value | e.setLabel(value)    ])
284
        setter.apply(LP__GE,       [e, value | e.setLp(value)       ])
285
        setter.apply(POS__NE,      [e, value | e.setPos(value)      ])
286
        setter.apply(STYLE__GNE,   [e, value | e.setStyle(value)    ])
287
        setter.apply(TAILLABEL__E, [e, value | e.setTailLabel(value)])
288
        setter.apply(TAIL_LP__E,   [e, value | e.setTailLp(value)   ])
289
        setter.apply(XLABEL__NE,   [e, value | e.setXLabel(value)   ])
290
        setter.apply(XLP__NE,      [e, value | e.setXlp(value)      ])
291
292
		graphBuilder.edges(edge)
293
	}
294
	
295
	def private String getAttributeValue(DotGraph graph, String name) {
296
		for (stmt : graph.stmts) {
297
			var String value =
298
				switch stmt {
299
					AttrStmt:  stmt.getAttributeValue(name)
300
					Attribute: stmt.getAttributeValue(name)
301
				}
302
			if (value != null) {
303
				return value
304
			}
305
		}
306
		null
307
	}
308
	
309
	/**
310
	 * Returns the value of the first attribute with the give name or
311
	 * <code>null</code> if no attribute could be found.
312
	 * 
313
	 * @param attrLists
314
	 *            The {@link AttrList}s to search.
315
	 * @param name
316
	 *            The name of the attribute whose value is to be retrieved.
317
	 * @return The attribute value or <code>null</code> in case the attribute
318
	 *         could not be found.
319
	 */
320
	def private String getAttributeValue(List<AttrList> attrLists, String name) {
321
		for (AttrList attrList : attrLists) {
322
			val value = attrList.getAttributeValue(name)
323
			if (value != null) {
324
				return value
325
			}
326
		}
327
		null
328
	}
329
	
330
	def private String getAttributeValue(AttrStmt attrStmt, String name) {
331
		attrStmt.attrLists.getAttributeValue(name)
332
	}
333
334
	def private String getAttributeValue(AttrList attrList, String name) {
335
		attrList.attributes.findFirst[it.name==name]?.value.escaped
336
	}
337
	
338
	def private String getAttributeValue(Attribute attribute, String name) {
339
		if (attribute.name.equals(name)) {
340
			return attribute.value.escaped
341
		}
342
		null
343
	}
344
	
345
	private def escaped(String it) {
346
		DotTerminalConverters.unquote(it)
347
	}
348
	
52
}
349
}
(-)a/org.eclipse.gef4.dot/src/org/eclipse/gef4/dot/internal/DotInterpreter.java (-600 lines)
Lines 1-600 Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009, 2016 Fabian Steeg and others.
3
 * 
4
 * All rights reserved. This program and the accompanying materials
5
 * are made available under the terms of the Eclipse Public License v1.0
6
 * which accompanies this distribution, and is available at
7
 * http://www.eclipse.org/legal/epl-v10.html
8
 *
9
 * Contributors:
10
 *     Fabian Steeg                - initial API and implementation (bug #277380)                     
11
 *     Alexander Nyßen (itemis AG) - several refactorings and additions (bugs #487081, #489793)
12
 *     Tamas Miklossy  (itemis AG) - support for arrowType edge decorations (bug #477980)
13
 *                                 - support for polygon-based node shapes (bug #441352)
14
 *                                   
15
 *******************************************************************************/
16
17
package org.eclipse.gef4.dot.internal;
18
19
import java.util.ArrayList;
20
import java.util.HashMap;
21
import java.util.Iterator;
22
import java.util.List;
23
import java.util.Map;
24
25
import org.eclipse.emf.common.util.TreeIterator;
26
import org.eclipse.emf.ecore.EObject;
27
import org.eclipse.emf.ecore.util.EcoreUtil;
28
import org.eclipse.gef4.dot.internal.parser.conversion.DotTerminalConverters;
29
import org.eclipse.gef4.dot.internal.parser.dot.AttrList;
30
import org.eclipse.gef4.dot.internal.parser.dot.AttrStmt;
31
import org.eclipse.gef4.dot.internal.parser.dot.Attribute;
32
import org.eclipse.gef4.dot.internal.parser.dot.AttributeType;
33
import org.eclipse.gef4.dot.internal.parser.dot.DotAst;
34
import org.eclipse.gef4.dot.internal.parser.dot.DotGraph;
35
import org.eclipse.gef4.dot.internal.parser.dot.EdgeRhsNode;
36
import org.eclipse.gef4.dot.internal.parser.dot.EdgeStmtNode;
37
import org.eclipse.gef4.dot.internal.parser.dot.GraphType;
38
import org.eclipse.gef4.dot.internal.parser.dot.NodeId;
39
import org.eclipse.gef4.dot.internal.parser.dot.NodeStmt;
40
import org.eclipse.gef4.dot.internal.parser.dot.Stmt;
41
import org.eclipse.gef4.dot.internal.parser.dot.util.DotSwitch;
42
import org.eclipse.gef4.dot.internal.parser.splines.Splines;
43
import org.eclipse.gef4.graph.Edge;
44
import org.eclipse.gef4.graph.Graph;
45
import org.eclipse.gef4.graph.Graph.Builder;
46
import org.eclipse.gef4.graph.Node;
47
48
/**
49
 * Create a {@link Graph} instance from a DOT string by interpreting the AST of
50
 * the parsed DOT.
51
 * 
52
 * @author Fabian Steeg (fsteeg)
53
 * @author Alexander Nyßen (anyssen)
54
 */
55
// TODO: merge this into DotImport; turning DotImport into an Xtend class (so we
56
// can use create functions)
57
public final class DotInterpreter extends DotSwitch<Object> {
58
59
	private Builder graphBuilder;
60
	private Map<String, Node> nodesByName = new HashMap<>();
61
62
	private Map<String, String> globalGraphAttributes = new HashMap<>();
63
	private Map<String, String> globalNodeAttributes = new HashMap<>();
64
	private Map<String, String> globalEdgeAttributes = new HashMap<>();
65
66
	private boolean createEdge;
67
	private String currentArrowHead;
68
	private String currentArrowTail;
69
	private String currentArrowSize;
70
	private String currentEdgeDirection;
71
	private String currentEdgeStyle;
72
	private String currentEdgeLabel;
73
	private String currentEdgeSourceNodeName;
74
	private String currentEdgePos;
75
	private String currentEdgeXLabel;
76
	private String currentEdgeXlp;
77
	private String currentEdgeLp;
78
	private String currentEdgeTailLabel;
79
	private String currentEdgeHeadLabel;
80
	private String currentEdgeHeadLp;
81
	private String currentEdgeTailLp;
82
	private String currentEdgeId;
83
	private String currentEdgeOp;
84
85
	/**
86
	 * @param dotAst
87
	 *            The DOT abstract syntax tree (AST) to interpret
88
	 * @return A graph instance for the given DOT AST
89
	 */
90
	public List<Graph> interpret(DotAst dotAst) {
91
		List<Graph> graphs = new ArrayList<>();
92
		for (DotGraph dotGraph : dotAst.getGraphs()) {
93
			// clear global attributes, which only hold for each respective
94
			// graph
95
			globalGraphAttributes.clear();
96
			globalNodeAttributes.clear();
97
			globalEdgeAttributes.clear();
98
99
			// create a new graph builder and clear the nodes map
100
			graphBuilder = new Graph.Builder();
101
			nodesByName.clear();
102
103
			// process all contents (nodes, edges, attributes)
104
			TreeIterator<Object> contents = EcoreUtil
105
					.getAllProperContents(dotGraph, false);
106
			while (contents.hasNext()) {
107
				doSwitch((EObject) contents.next());
108
			}
109
110
			// process the graph last, so we can initialize attributes of the
111
			// created graph object rather than using the builder; we can thus
112
			// ensure attribute values get properly validated.
113
			Graph g = (Graph) doSwitch(dotGraph);
114
			if (g != null) {
115
				graphs.add(g);
116
			}
117
		}
118
		return graphs;
119
	}
120
121
	@Override
122
	public Object caseDotGraph(DotGraph dotGraph) {
123
		// name (meta-attribute)
124
		String name = escaped(dotGraph.getName());
125
		if (name != null) {
126
			graphBuilder.attr(DotAttributes._NAME__GNE, name);
127
		}
128
129
		// type (meta-attribute)
130
		GraphType graphType = dotGraph.getType();
131
		graphBuilder.attr(DotAttributes._TYPE__G,
132
				GraphType.GRAPH.equals(graphType)
133
						? DotAttributes._TYPE__G__GRAPH
134
						: DotAttributes._TYPE__G__DIGRAPH);
135
		Graph graph = graphBuilder.build();
136
137
		// layout
138
		String layout = getAttributeValue(dotGraph, DotAttributes.LAYOUT__G);
139
		if (layout != null) {
140
			DotAttributes.setLayout(graph, layout);
141
		} else if (globalGraphAttributes.containsKey(DotAttributes.LAYOUT__G)) {
142
			DotAttributes.setLayout(graph,
143
					globalGraphAttributes.get(DotAttributes.LAYOUT__G));
144
		}
145
		// rankdir
146
		String rankdir = getAttributeValue(dotGraph, DotAttributes.RANKDIR__G);
147
		if (rankdir != null) {
148
			DotAttributes.setRankdir(graph, rankdir);
149
		} else if (globalGraphAttributes
150
				.containsKey(DotAttributes.RANKDIR__G)) {
151
			DotAttributes.setRankdir(graph,
152
					globalGraphAttributes.get(DotAttributes.RANKDIR__G));
153
		}
154
		// splines
155
		String splines = getAttributeValue(dotGraph, DotAttributes.SPLINES__G);
156
		if (splines == null && globalGraphAttributes
157
				.containsKey(DotAttributes.SPLINES__G)) {
158
			splines = globalGraphAttributes.get(DotAttributes.SPLINES__G);
159
		}
160
		if (splines != null) {
161
			// XXX: splines can either be a defined enum value or a bool value
162
			// (which is mapped to respective enum values); we use the enum
163
			// values alone and thus map the bool value here
164
			Boolean booleanValue = DotLanguageSupport.parseAttributeValue(
165
					DotLanguageSupport.BOOL_PARSER, splines);
166
			if (booleanValue != null) {
167
				DotAttributes.setSplinesParsed(graph,
168
						Boolean.TRUE.equals(booleanValue) ? Splines.TRUE
169
								: Splines.FALSE);
170
			} else {
171
				DotAttributes.setSplines(graph, splines);
172
			}
173
		}
174
		return graph;
175
	}
176
177
	@Override
178
	public Object caseAttrStmt(AttrStmt attrStmt) {
179
		AttributeType type = attrStmt.getType();
180
		switch (type) {
181
		case EDGE: {
182
			// global edge attributes
183
			for (AttrList al : attrStmt.getAttrLists()) {
184
				for (Attribute a : al.getAttributes()) {
185
					globalEdgeAttributes.put(a.getName(),
186
							escaped(a.getValue()));
187
				}
188
			}
189
			break;
190
		}
191
		case NODE: {
192
			// global node attributes
193
			for (AttrList al : attrStmt.getAttrLists()) {
194
				for (Attribute a : al.getAttributes()) {
195
					globalNodeAttributes.put(a.getName(),
196
							escaped(a.getValue()));
197
				}
198
			}
199
			break;
200
		}
201
		case GRAPH: {
202
			// global graph attributes
203
			for (AttrList al : attrStmt.getAttrLists()) {
204
				for (Attribute a : al.getAttributes()) {
205
					globalGraphAttributes.put(a.getName(),
206
							escaped(a.getValue()));
207
				}
208
			}
209
			break;
210
		}
211
		}
212
		return super.caseAttrStmt(attrStmt);
213
	}
214
215
	@Override
216
	public Object caseNodeStmt(NodeStmt nodeStmt) {
217
		// name (from grammar definition, not attribute)
218
		Node node = node(escaped(nodeStmt.getNode().getName()));
219
220
		// distortion
221
		String distortion = getAttributeValue(nodeStmt,
222
				DotAttributes.DISTORTION__N);
223
		if (distortion != null) {
224
			DotAttributes.setDistortion(node, distortion);
225
		}
226
227
		// id
228
		String id = getAttributeValue(nodeStmt, DotAttributes.ID__GNE);
229
		if (id != null) {
230
			DotAttributes.setId(node, id);
231
		}
232
233
		// label
234
		String label = getAttributeValue(nodeStmt, DotAttributes.LABEL__GNE);
235
		if (label != null) {
236
			DotAttributes.setLabel(node, label);
237
		}
238
239
		// xlabel
240
		String xLabel = getAttributeValue(nodeStmt, DotAttributes.XLABEL__NE);
241
		if (xLabel != null) {
242
			DotAttributes.setXLabel(node, xLabel);
243
		}
244
245
		// pos
246
		String pos = getAttributeValue(nodeStmt, DotAttributes.POS__NE);
247
		if (pos != null) {
248
			DotAttributes.setPos(node, pos);
249
		}
250
251
		// xlp
252
		String xlp = getAttributeValue(nodeStmt, DotAttributes.XLP__NE);
253
		if (xlp != null) {
254
			DotAttributes.setXlp(node, xlp);
255
		}
256
257
		// width
258
		String width = getAttributeValue(nodeStmt, DotAttributes.WIDTH__N);
259
		if (width != null) {
260
			DotAttributes.setWidth(node, width);
261
		}
262
263
		// height
264
		String height = getAttributeValue(nodeStmt, DotAttributes.HEIGHT__N);
265
		if (height != null) {
266
			DotAttributes.setHeight(node, height);
267
		}
268
269
		// fixedsize
270
		String fixedSize = getAttributeValue(nodeStmt,
271
				DotAttributes.FIXEDSIZE__N);
272
		if (fixedSize != null) {
273
			DotAttributes.setFixedSize(node, fixedSize);
274
		}
275
276
		// shape
277
		String shape = getAttributeValue(nodeStmt, DotAttributes.SHAPE__N);
278
		if (shape != null) {
279
			DotAttributes.setShape(node, shape);
280
		}
281
282
		// sides
283
		String sides = getAttributeValue(nodeStmt, DotAttributes.SIDES__N);
284
		if (sides != null) {
285
			DotAttributes.setSides(node, sides);
286
		}
287
288
		// skew
289
		String skew = getAttributeValue(nodeStmt, DotAttributes.SKEW__N);
290
		if (skew != null) {
291
			DotAttributes.setSkew(node, skew);
292
		}
293
294
		// style
295
		String style = getAttributeValue(nodeStmt, DotAttributes.STYLE__GNE);
296
		if (style != null) {
297
			DotAttributes.setStyle(node, style);
298
		}
299
		return super.caseNodeStmt(nodeStmt);
300
	}
301
302
	@Override
303
	public Object caseEdgeStmtNode(EdgeStmtNode object) {
304
		currentEdgeId = getAttributeValue(object, DotAttributes.ID__GNE);
305
		currentEdgeLabel = getAttributeValue(object, DotAttributes.LABEL__GNE);
306
		currentEdgeLp = getAttributeValue(object, DotAttributes.LP__GE);
307
		currentEdgeXLabel = getAttributeValue(object, DotAttributes.XLABEL__NE);
308
		currentEdgeXlp = getAttributeValue(object, DotAttributes.XLP__NE);
309
		currentEdgeStyle = getAttributeValue(object, DotAttributes.STYLE__GNE);
310
		currentEdgePos = getAttributeValue(object, DotAttributes.POS__NE);
311
		currentEdgeHeadLabel = getAttributeValue(object,
312
				DotAttributes.HEADLABEL__E);
313
		currentEdgeHeadLp = getAttributeValue(object, DotAttributes.HEAD_LP__E);
314
		currentEdgeTailLabel = getAttributeValue(object,
315
				DotAttributes.TAILLABEL__E);
316
		currentEdgeTailLp = getAttributeValue(object, DotAttributes.TAIL_LP__E);
317
		currentArrowHead = getAttributeValue(object,
318
				DotAttributes.ARROWHEAD__E);
319
		currentArrowTail = getAttributeValue(object,
320
				DotAttributes.ARROWTAIL__E);
321
		currentArrowSize = getAttributeValue(object,
322
				DotAttributes.ARROWSIZE__E);
323
		currentEdgeDirection = getAttributeValue(object, DotAttributes.DIR__E);
324
		return super.caseEdgeStmtNode(object);
325
	}
326
327
	@Override
328
	public Object caseNodeId(NodeId object) {
329
		if (!createEdge) {
330
			currentEdgeSourceNodeName = escaped(object.getName());
331
		} else {
332
			String targetNodeName = escaped(object.getName());
333
			if (currentEdgeSourceNodeName != null && targetNodeName != null) {
334
				edge(currentEdgeSourceNodeName, currentEdgeOp, targetNodeName);
335
				// current target node may be source for next EdgeRHS
336
				currentEdgeSourceNodeName = targetNodeName;
337
			}
338
			createEdge = false;
339
		}
340
		return super.caseNodeId(object);
341
	}
342
343
	private void edge(String sourceNodeName, String edgeOp,
344
			String targetNodeName) {
345
		Edge edge = new Edge.Builder(node(sourceNodeName), node(targetNodeName))
346
				.attr(DotAttributes._NAME__GNE,
347
						sourceNodeName + edgeOp + targetNodeName)
348
				.buildEdge();
349
350
		// id
351
		if (currentEdgeId != null) {
352
			DotAttributes.setId(edge, currentEdgeId);
353
		}
354
355
		// label
356
		if (currentEdgeLabel != null) {
357
			DotAttributes.setLabel(edge, currentEdgeLabel);
358
		} else if (globalEdgeAttributes.containsKey(DotAttributes.LABEL__GNE)) {
359
			DotAttributes.setLabel(edge,
360
					globalEdgeAttributes.get(DotAttributes.LABEL__GNE));
361
		}
362
363
		// external label (xlabel)
364
		if (currentEdgeXLabel != null) {
365
			DotAttributes.setXLabel(edge, currentEdgeXLabel);
366
		} else if (globalEdgeAttributes.containsKey(DotAttributes.XLABEL__NE)) {
367
			DotAttributes.setXLabel(edge,
368
					globalEdgeAttributes.get(DotAttributes.XLABEL__NE));
369
		}
370
371
		// head label (headllabel)
372
		if (currentEdgeHeadLabel != null) {
373
			DotAttributes.setHeadLabel(edge, currentEdgeHeadLabel);
374
		} else if (globalEdgeAttributes
375
				.containsKey(DotAttributes.HEADLABEL__E)) {
376
			DotAttributes.setHeadLabel(edge,
377
					globalEdgeAttributes.get(DotAttributes.HEADLABEL__E));
378
		}
379
380
		// tail label (taillabel)
381
		if (currentEdgeTailLabel != null) {
382
			DotAttributes.setTailLabel(edge, currentEdgeTailLabel);
383
		} else if (globalEdgeAttributes
384
				.containsKey(DotAttributes.TAILLABEL__E)) {
385
			DotAttributes.setTailLabel(edge,
386
					globalEdgeAttributes.get(DotAttributes.TAILLABEL__E));
387
		}
388
389
		// style
390
		if (currentEdgeStyle != null) {
391
			DotAttributes.setStyle(edge, currentEdgeStyle);
392
		} else if (globalEdgeAttributes.containsKey(DotAttributes.STYLE__GNE)) {
393
			DotAttributes.setStyle(edge,
394
					globalEdgeAttributes.get(DotAttributes.STYLE__GNE));
395
		}
396
397
		// arrow head
398
		if (currentArrowHead != null) {
399
			DotAttributes.setArrowHead(edge, currentArrowHead);
400
		} else if (globalEdgeAttributes
401
				.containsKey(DotAttributes.ARROWHEAD__E)) {
402
			DotAttributes.setArrowHead(edge,
403
					globalEdgeAttributes.get(DotAttributes.ARROWHEAD__E));
404
		}
405
406
		// arrow tail
407
		if (currentArrowTail != null) {
408
			DotAttributes.setArrowTail(edge, currentArrowTail);
409
		} else if (globalEdgeAttributes
410
				.containsKey(DotAttributes.ARROWTAIL__E)) {
411
			DotAttributes.setArrowTail(edge,
412
					globalEdgeAttributes.get(DotAttributes.ARROWTAIL__E));
413
		}
414
415
		// arrow size
416
		if (currentArrowSize != null) {
417
			DotAttributes.setArrowSize(edge, currentArrowSize);
418
		} else if (globalEdgeAttributes
419
				.containsKey(DotAttributes.ARROWSIZE__E)) {
420
			DotAttributes.setArrowSize(edge,
421
					globalEdgeAttributes.get(DotAttributes.ARROWSIZE__E));
422
		}
423
424
		// direction
425
		if (currentEdgeDirection != null) {
426
			DotAttributes.setDir(edge, currentEdgeDirection);
427
		} else if (globalEdgeAttributes.containsKey(DotAttributes.DIR__E)) {
428
			DotAttributes.setDir(edge,
429
					globalEdgeAttributes.get(DotAttributes.DIR__E));
430
		}
431
432
		// position (pos)
433
		if (currentEdgePos != null) {
434
			DotAttributes.setPos(edge, currentEdgePos);
435
		}
436
		// label position (lp)
437
		if (currentEdgeLp != null) {
438
			DotAttributes.setLp(edge, currentEdgeLp);
439
		}
440
441
		// external label position (xlp)
442
		if (currentEdgeXlp != null) {
443
			DotAttributes.setXlp(edge, currentEdgeXlp);
444
		}
445
446
		// head label position (head_lp)
447
		if (currentEdgeHeadLp != null) {
448
			DotAttributes.setHeadLp(edge, currentEdgeHeadLp);
449
		}
450
451
		// tail label position (tail_lp)
452
		if (currentEdgeTailLp != null) {
453
			DotAttributes.setTailLp(edge, currentEdgeTailLp);
454
		}
455
456
		graphBuilder.edges(edge);
457
	}
458
459
	@Override
460
	public Object caseEdgeRhsNode(EdgeRhsNode object) {
461
		// Set the flag for the node_id case handled above
462
		createEdge = true;
463
		currentEdgeOp = object.getOp().getLiteral();
464
		return super.caseEdgeRhsNode(object);
465
	}
466
467
	private Node node(String nodeName) {
468
		if (!nodesByName.containsKey(nodeName)) {
469
			Node node = new Node.Builder()
470
					.attr(DotAttributes._NAME__GNE, nodeName).buildNode();
471
			graphBuilder.nodes(node);
472
			nodesByName.put(nodeName, node);
473
474
			// evaluate global attributes
475
			if (globalNodeAttributes.containsKey(DotAttributes.LABEL__GNE)) {
476
				DotAttributes.setLabel(node,
477
						globalNodeAttributes.get(DotAttributes.LABEL__GNE));
478
			}
479
			if (globalNodeAttributes.containsKey(DotAttributes.XLABEL__NE)) {
480
				DotAttributes.setXLabel(node,
481
						globalNodeAttributes.get(DotAttributes.XLABEL__NE));
482
			}
483
			if (globalNodeAttributes.containsKey(DotAttributes.WIDTH__N)) {
484
				DotAttributes.setWidth(node,
485
						globalNodeAttributes.get(DotAttributes.WIDTH__N));
486
			}
487
			if (globalNodeAttributes.containsKey(DotAttributes.HEIGHT__N)) {
488
				DotAttributes.setHeight(node,
489
						globalNodeAttributes.get(DotAttributes.HEIGHT__N));
490
			}
491
			if (globalNodeAttributes.containsKey(DotAttributes.FIXEDSIZE__N)) {
492
				DotAttributes.setFixedSize(node,
493
						globalNodeAttributes.get(DotAttributes.FIXEDSIZE__N));
494
			}
495
			if (globalNodeAttributes.containsKey(DotAttributes.DISTORTION__N)) {
496
				DotAttributes.setDistortion(node,
497
						globalNodeAttributes.get(DotAttributes.DISTORTION__N));
498
			}
499
			if (globalNodeAttributes.containsKey(DotAttributes.SHAPE__N)) {
500
				DotAttributes.setShape(node,
501
						globalNodeAttributes.get(DotAttributes.SHAPE__N));
502
			}
503
			if (globalNodeAttributes.containsKey(DotAttributes.SIDES__N)) {
504
				DotAttributes.setSides(node,
505
						globalNodeAttributes.get(DotAttributes.SIDES__N));
506
			}
507
			if (globalNodeAttributes.containsKey(DotAttributes.SKEW__N)) {
508
				DotAttributes.setSkew(node,
509
						globalNodeAttributes.get(DotAttributes.SKEW__N));
510
			}
511
			if (globalNodeAttributes.containsKey(DotAttributes.STYLE__GNE)) {
512
				DotAttributes.setStyle(node,
513
						globalNodeAttributes.get(DotAttributes.STYLE__GNE));
514
			}
515
		}
516
		return nodesByName.get(nodeName);
517
	}
518
519
	private String getAttributeValue(final DotGraph graph, final String name) {
520
		for (Stmt stmt : graph.getStmts()) {
521
			String value = null;
522
			if (stmt instanceof AttrStmt) {
523
				value = getAttributeValue((AttrStmt) stmt, name);
524
			} else if (stmt instanceof Attribute) {
525
				value = getAttributeValue((Attribute) stmt, name);
526
			}
527
			if (value != null) {
528
				return value;
529
			}
530
		}
531
		return null;
532
	}
533
534
	/**
535
	 * @param stmt
536
	 *            The {@link NodeStmt} object, e.g. the object corresponding to
537
	 *            "node[label="hi"]"
538
	 * @param name
539
	 *            The name of the attribute to get the value for, e.g. "label"
540
	 * @return The value of the given attribute, e.g. "hi"
541
	 */
542
	private String getAttributeValue(final NodeStmt stmt, final String name) {
543
		return getAttributeValue(stmt.getAttrLists(), name);
544
	}
545
546
	/**
547
	 * Returns the value of the first attribute with the give name or
548
	 * <code>null</code> if no attribute could be found.
549
	 * 
550
	 * @param attrLists
551
	 *            The {@link AttrList}s to search.
552
	 * @param name
553
	 *            The name of the attribute whose value is to be retrieved.
554
	 * @return The attribute value or <code>null</code> in case the attribute
555
	 *         could not be found.
556
	 */
557
	private String getAttributeValue(List<AttrList> attrLists,
558
			final String name) {
559
		for (AttrList attrList : attrLists) {
560
			String value = getAttributeValue(attrList, name);
561
			if (value != null) {
562
				return value;
563
			}
564
		}
565
		return null;
566
	}
567
568
	private String getAttributeValue(AttrStmt attrStmt, String name) {
569
		return getAttributeValue(attrStmt.getAttrLists(), name);
570
	}
571
572
	private String getAttributeValue(EdgeStmtNode edgeStmtNode, String name) {
573
		return getAttributeValue(edgeStmtNode.getAttrLists(), name);
574
	}
575
576
	private String getAttributeValue(AttrList attrList, final String name) {
577
		Iterator<EObject> attributeContents = attrList.eContents().iterator();
578
		while (attributeContents.hasNext()) {
579
			EObject next = attributeContents.next();
580
			if (next instanceof Attribute) {
581
				String value = getAttributeValue((Attribute) next, name);
582
				if (value != null) {
583
					return value;
584
				}
585
			}
586
		}
587
		return null;
588
	}
589
590
	private String getAttributeValue(Attribute attribute, final String name) {
591
		if (attribute.getName().equals(name)) {
592
			return escaped(attribute.getValue());
593
		}
594
		return null;
595
	}
596
597
	private String escaped(String id) {
598
		return DotTerminalConverters.unquote(id);
599
	}
600
}

Return to bug 491261