8 * Copyright (c) 2012-2013 Nicholas J Humfrey. All rights reserved.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright notice,
15 * this list of conditions and the following disclaimer in the documentation
16 * and/or other materials provided with the distribution.
17 * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
18 * promote products derived from this software without specific prior
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
34 * @copyright Copyright (c) 2009-2013 Nicholas J Humfrey
35 * @license http://www.opensource.org/licenses/bsd-license.php
39 * Class to serialise an EasyRdf_Graph to GraphViz
41 * Depends upon the GraphViz 'dot' command line tools to render images.
43 * See http://www.graphviz.org/ for more information.
46 * @copyright Copyright (c) 2012-2013 Nicholas J Humfrey
47 * @license http://www.opensource.org/licenses/bsd-license.php
49 class EasyRdf_Serialiser_GraphViz extends EasyRdf_Serialiser
51 private $dotCommand = 'dot';
52 private $useLabels = false;
53 private $onlyLabelled = false;
54 private $attributes = array('charset' => 'utf-8');
59 * @return object EasyRdf_Serialiser_GraphViz
61 public function __construct()
66 * Set the path to the GraphViz 'dot' command
68 * Default is to search PATH for the command 'dot'.
70 * @param string $cmd The path to the 'dot' command.
71 * @return object EasyRdf_Serialiser_GraphViz
73 public function setDotCommand($cmd)
75 $this->dotCommand = $cmd;
80 * Get the path to the GraphViz 'dot' command
82 * The default value is simply 'dot'
84 * @return string The path to the 'dot' command.
86 public function getDotCommand()
88 return $this->dotCommand;
92 * Turn on/off the option to display labels instead of URIs.
94 * When this option is turned on, then labels for resources will
95 * be displayed instead of the full URI of a resource. This makes
96 * it simpler to create friendly diagrams that non-technical people
99 * This option is turned off by default.
101 * @param bool $useLabels A boolean value to turn labels on and off
102 * @return object EasyRdf_Serialiser_GraphViz
104 public function setUseLabels($useLabels)
106 $this->useLabels = $useLabels;
111 * Get the state of the use labels option
113 * @return bool The current state of the use labels option
115 public function getUseLabels()
117 return $this->useLabels;
121 * Turn on/off the option to only display nodes and edges with labels
123 * When this option is turned on, then only nodes (resources and literals)
124 * and edges (properties) will only be displayed if they have a label. You
125 * can use this option, to create concise, diagrams of your data, rather than
128 * This option is turned off by default.
130 * @param bool $onlyLabelled A boolean value to enable/display only labelled items
131 * @return object EasyRdf_Serialiser_GraphViz
133 public function setOnlyLabelled($onlyLabelled)
135 $this->onlyLabelled = $onlyLabelled;
140 * Get the state of the only Only Labelled option
142 * @return bool The current state of the Only Labelled option
144 public function getOnlyLabelled()
146 return $this->onlyLabelled;
150 * Set an attribute on the GraphViz graph
153 * $serialiser->setAttribute('rotate', 90);
155 * See the GraphViz tool documentation for information about the
156 * available attributes.
158 * @param string $name The name of the attribute
159 * @param string $value The value for the attribute
160 * @return object EasyRdf_Serialiser_GraphViz
162 public function setAttribute($name, $value)
164 $this->attributes[$name] = $value;
169 * Get an attribute of the GraphViz graph
171 * @param string $name Attribute name
172 * @return string The value of the graph attribute
174 public function getAttribute($name)
176 return $this->attributes[$name];
180 * Convert an EasyRdf object into a GraphViz node identifier
184 protected function nodeName($entity)
186 if ($entity instanceof EasyRdf_Resource) {
187 if ($entity->isBNode()) {
188 return "B".$entity->getUri();
190 return "R".$entity->getUri();
198 * Internal function to escape a string into DOT safe syntax
202 protected function escape($input)
204 if (preg_match('/^([a-z_][a-z_0-9]*|-?(\.[0-9]+|[0-9]+(\.[0-9]*)?))$/i', $input)) {
207 return '"'.str_replace(
208 array("\r\n", "\n", "\r", '"'),
209 array('\n', '\n', '\n', '\"'),
216 * Internal function to escape an associate array of attributes and
217 * turns it into a DOT notation string
221 protected function escapeAttributes($array)
224 foreach ($array as $k => $v) {
225 $items[] = $this->escape($k).'='.$this->escape($v);
227 return '['.implode(',', $items).']';
231 * Internal function to create dot syntax line for either a node or an edge
235 protected function serialiseRow($node1, $node2 = null, $attributes = array())
237 $result = ' '.$this->escape($node1);
239 $result .= ' -> '.$this->escape($node2);
241 if (count($attributes)) {
242 $result .= ' '.$this->escapeAttributes($attributes);
244 return $result.";\n";
248 * Internal function to serialise an EasyRdf_Graph into a DOT formatted string
252 protected function serialiseDot($graph)
254 $result = "digraph {\n";
256 // Write the graph attributes
257 foreach ($this->attributes as $k => $v) {
258 $result .= ' '.$this->escape($k).'='.$this->escape($v).";\n";
261 // Go through each of the properties and write the edges
263 $result .= "\n // Edges\n";
264 foreach ($graph->resources() as $resource) {
265 $name1 = $this->nodeName($resource);
266 foreach ($resource->propertyUris() as $property) {
268 if ($this->useLabels) {
269 $label = $graph->resource($property)->label();
271 if ($label === null) {
272 if ($this->onlyLabelled == true) {
275 $label = EasyRdf_Namespace::shorten($property);
278 foreach ($resource->all("<$property>") as $value) {
279 $name2 = $this->nodeName($value);
280 $nodes[$name1] = $resource;
281 $nodes[$name2] = $value;
282 $result .= $this->serialiseRow(
285 array('label' => $label)
293 $result .= "\n // Nodes\n";
294 foreach ($nodes as $name => $node) {
295 $type = substr($name, 0, 1);
298 if ($this->useLabels) {
299 $label = $node->label();
302 $label = $node->shorten();
305 $label = $node->getURI();
307 $result .= $this->serialiseRow(
311 'URL' => $node->getURI(),
313 'shape' => 'ellipse',
317 } elseif ($type == 'B') {
318 if ($this->useLabels) {
319 $label = $node->label();
321 $result .= $this->serialiseRow(
331 $result .= $this->serialiseRow(
335 'label' => strval($node),
349 * Internal function to render a graph into an image
353 public function renderImage($graph, $format = 'png')
355 $dot = $this->serialiseDot($graph);
357 return EasyRdf_Utils::execCommandPipe(
365 * Serialise an EasyRdf_Graph into a GraphViz dot document.
367 * Supported output format names: dot, gif, png, svg
369 * @param EasyRdf_Graph $graph An EasyRdf_Graph object.
370 * @param string $format The name of the format to convert to.
371 * @param array $options
372 * @throws EasyRdf_Exception
373 * @return string The RDF in the new desired format.
375 public function serialise($graph, $format, array $options = array())
377 parent::checkSerialiseParams($graph, $format);
381 return $this->serialiseDot($graph);
385 return $this->renderImage($graph, $format);
387 throw new EasyRdf_Exception(
388 "EasyRdf_Serialiser_GraphViz does not support: $format"