org.graphstream.util.VerboseSink Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gs-core Show documentation
Show all versions of gs-core Show documentation
The GraphStream library. With GraphStream you deal with
graphs. Static and Dynamic. You create them from scratch, from a file
or any source. You display and render them. This is the core package
that contains the minimal needed to read and write a graph.
/*
* Copyright 2006 - 2015
* Stefan Balev
* Julien Baudry
* Antoine Dutot
* Yoann Pigné
* Guilhelm Savin
*
* This file is part of GraphStream .
*
* GraphStream is a library whose purpose is to handle static or dynamic
* graph, create them from scratch, file or any source and display them.
*
* This program is free software distributed under the terms of two licenses, the
* CeCILL-C license that fits European law, and the GNU Lesser General Public
* License. You can use, modify and/ or redistribute the software under the terms
* of the CeCILL-C license as circulated by CEA, CNRS and INRIA at the following
* URL or under the terms of the GNU LGPL 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*
* The fact that you are presently reading this means that you have had
* knowledge of the CeCILL-C and LGPL licenses and that you accept their terms.
*/
package org.graphstream.util;
import java.io.PrintStream;
import java.lang.reflect.Array;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Stack;
import org.graphstream.stream.Sink;
/**
* A sink that can be used to display event in a PrintStream like System.out.
* Format of messages can be customized, inserting keywords quoted with '%' in
* the format.
*
* '%sourceId%' and '%timeId%' keywords are defined for each event. Following
* defines keywords available for each event types:
*
* - ADD_NODE
* -
*
* - %nodeId%
*
*
* - ADD_NODE_ATTRIBUTE
* -
*
* - %nodeId%
* - %attributeId%
* - %value%
*
*
* - SET_NODE_ATTRIBUTE
* -
*
* - %nodeId%
* - %attributeId%
* - %value%
*
*
* - DEL_NODE_ATTRIBUTE
* -
*
* - %nodeId%
* - %attributeId%
*
*
* - DEL_NODE
* -
*
* - %nodeId%
*
*
* - ADD_EDGE
* -
*
* - %edgeId%
* - %source%
* - %target%
* - %directed%
*
*
* - ADD_EDGE_ATTRIBUTE
* -
*
* - %edgeId%
* - %attributeId%
* - %value%
*
*
* - SET_EDGE_ATTRIBUTE
* -
*
* - %edgeId%
* - %attributeId%
* - %value%
*
*
* - DEL_EDGE_ATTRIBUTE
* -
*
* - %edgeId%
* - %attributeId%
*
*
* - DEL_EDGE
* -
*
* - %edgeId%
*
*
* - ADD_GRAPH_ATTRIBUTE
* -
*
* - %attributeId%
* - %value%
*
*
* - SET_GRAPH_ATTRIBUTE
* -
*
* - %attributeId%
* - %value%
*
*
* - DEL_GRAPH_ATTRIBUTE
* -
*
* - %attributeId%
*
*
* - CLEAR
*
* - STEP_BEGINS
* -
*
* - %step%
*
*
*
*/
public class VerboseSink implements Sink {
public static final String DEFAULT_AN_FORMAT = "%prefix%[%sourceId%:%timeId%] add node \"%nodeId%\"%suffix%";
public static final String DEFAULT_CNA_FORMAT = "%prefix%[%sourceId%:%timeId%] set node \"%nodeId%\" +\"%attributeId%\"=%value%%suffix%";
public static final String DEFAULT_CNC_FORMAT = "%prefix%[%sourceId%:%timeId%] set node \"%nodeId%\" \"%attributeId%\"=%value%%suffix%";
public static final String DEFAULT_CNR_FORMAT = "%prefix%[%sourceId%:%timeId%] set node \"%nodeId%\" -\"%attributeId%\"%suffix%";
public static final String DEFAULT_DN_FORMAT = "%prefix%[%sourceId%:%timeId%] remove node \"%nodeId%\"%suffix%";
public static final String DEFAULT_AE_FORMAT = "%prefix%[%sourceId%:%timeId%] add edge \"%edgeId%\" : \"%source%\" -- \"%target%\"%suffix%";
public static final String DEFAULT_CEA_FORMAT = "%prefix%[%sourceId%:%timeId%] set edge \"%edgeId%\" +\"%attributeId%\"=%value%%suffix%";
public static final String DEFAULT_CEC_FORMAT = "%prefix%[%sourceId%:%timeId%] set edge \"%edgeId%\" \"%attributeId%\"=%value%%suffix%";
public static final String DEFAULT_CER_FORMAT = "%prefix%[%sourceId%:%timeId%] set edge \"%edgeId%\" -\"%attributeId%\"%suffix%";
public static final String DEFAULT_DE_FORMAT = "%prefix%[%sourceId%:%timeId%] remove edge \"%edgeId%\"%suffix%";
public static final String DEFAULT_CGA_FORMAT = "%prefix%[%sourceId%:%timeId%] set +\"%attributeId%\"=%value%%suffix%";
public static final String DEFAULT_CGC_FORMAT = "%prefix%[%sourceId%:%timeId%] set \"%attributeId%\"=%value%%suffix%";
public static final String DEFAULT_CGR_FORMAT = "%prefix%[%sourceId%:%timeId%] set -\"%attributeId%\"%suffix%";
public static final String DEFAULT_CL_FORMAT = "%prefix%[%sourceId%:%timeId%] clear%suffix%";
public static final String DEFAULT_ST_FORMAT = "%prefix%[%sourceId%:%timeId%] step %step% begins%suffix%";
/*
* Shortcut to use HashMap.
*/
private static class Args extends HashMap {
private static final long serialVersionUID = 3064164898156692557L;
}
/**
* Enumeration defining type of events.
*
*/
public static enum EventType {
ADD_NODE, ADD_NODE_ATTRIBUTE, SET_NODE_ATTRIBUTE, DEL_NODE_ATTRIBUTE, DEL_NODE, ADD_EDGE, ADD_EDGE_ATTRIBUTE, SET_EDGE_ATTRIBUTE, DEL_EDGE_ATTRIBUTE, DEL_EDGE, ADD_GRAPH_ATTRIBUTE, SET_GRAPH_ATTRIBUTE, DEL_GRAPH_ATTRIBUTE, CLEAR, STEP_BEGINS
}
/**
* Flag used to indicate if the sink has to flush the output when writting a
* message.
*/
protected boolean autoflush;
/**
* Stream used to write message.
*/
protected final PrintStream out;
/**
* Format of messages associated with each event.
*/
protected final EnumMap formats;
/**
* Flag used to indicate if an event has to be written or note.
*/
protected final EnumMap enable;
/*
* Used to avoid to create a lot of hashmap when passing event arguments.
*/
private final Stack argsStack;
protected String prefix;
protected String suffix;
/**
* Create a new verbose sink using System.out.
*/
public VerboseSink() {
this(System.out);
}
/**
* Create a new verbose sink.
*
* @param out
* stream used to output message
*/
public VerboseSink(PrintStream out) {
this.out = out;
argsStack = new Stack();
enable = new EnumMap(EventType.class);
formats = new EnumMap(EventType.class);
formats.put(EventType.ADD_NODE, DEFAULT_AN_FORMAT);
formats.put(EventType.ADD_NODE_ATTRIBUTE, DEFAULT_CNA_FORMAT);
formats.put(EventType.SET_NODE_ATTRIBUTE, DEFAULT_CNC_FORMAT);
formats.put(EventType.DEL_NODE_ATTRIBUTE, DEFAULT_CNR_FORMAT);
formats.put(EventType.DEL_NODE, DEFAULT_DN_FORMAT);
formats.put(EventType.ADD_EDGE, DEFAULT_AE_FORMAT);
formats.put(EventType.ADD_EDGE_ATTRIBUTE, DEFAULT_CEA_FORMAT);
formats.put(EventType.SET_EDGE_ATTRIBUTE, DEFAULT_CEC_FORMAT);
formats.put(EventType.DEL_EDGE_ATTRIBUTE, DEFAULT_CER_FORMAT);
formats.put(EventType.DEL_EDGE, DEFAULT_DE_FORMAT);
formats.put(EventType.ADD_GRAPH_ATTRIBUTE, DEFAULT_CGA_FORMAT);
formats.put(EventType.SET_GRAPH_ATTRIBUTE, DEFAULT_CGC_FORMAT);
formats.put(EventType.DEL_GRAPH_ATTRIBUTE, DEFAULT_CGR_FORMAT);
formats.put(EventType.CLEAR, DEFAULT_CL_FORMAT);
formats.put(EventType.STEP_BEGINS, DEFAULT_ST_FORMAT);
for (EventType t : EventType.values())
enable.put(t, Boolean.TRUE);
suffix = "";
prefix = "";
}
/**
* Enable or disable autoflush.
*
* @param on
* true to enable autoflush
*/
public void setAutoFlush(boolean on) {
this.autoflush = on;
}
/**
* Redefines message format of an event.
*
* @param type
* type of the event
* @param format
* new format of the message attached with the event
*/
public void setEventFormat(EventType type, String format) {
formats.put(type, format);
}
/**
* Enable or disable an event.
*
* @param type
* type of the event
* @param on
* true to enable message for this event
*/
public void setEventEnabled(EventType type, boolean on) {
enable.put(type, on);
}
/**
* Enable or disable all messages associated with attribute events.
*
* @param on
* true to enable events
*/
public void setElementEventEnabled(boolean on) {
enable.put(EventType.ADD_EDGE_ATTRIBUTE, on);
enable.put(EventType.SET_EDGE_ATTRIBUTE, on);
enable.put(EventType.DEL_EDGE_ATTRIBUTE, on);
enable.put(EventType.ADD_NODE_ATTRIBUTE, on);
enable.put(EventType.SET_NODE_ATTRIBUTE, on);
enable.put(EventType.DEL_NODE_ATTRIBUTE, on);
enable.put(EventType.ADD_GRAPH_ATTRIBUTE, on);
enable.put(EventType.SET_GRAPH_ATTRIBUTE, on);
enable.put(EventType.DEL_GRAPH_ATTRIBUTE, on);
}
/**
* Enable or disable all messages associated with element events.
*
* @param on
* true to enable events
*/
public void setAttributeEventEnabled(boolean on) {
enable.put(EventType.ADD_EDGE, on);
enable.put(EventType.DEL_EDGE, on);
enable.put(EventType.ADD_NODE, on);
enable.put(EventType.DEL_NODE, on);
enable.put(EventType.CLEAR, on);
}
/**
* Set prefix used in messages.
*
* @param prefix
* new prefix
*/
public void setPrefix(String prefix) {
this.prefix = prefix;
}
/**
* Set suffix used in messages.
*
* @param suffix
* new suffix
*/
public void setSuffix(String suffix) {
this.suffix = suffix;
}
private void print(EventType type, Args args) {
if (!enable.get(type))
return;
String out = formats.get(type);
for (String k : args.keySet()) {
Object o = args.get(k);
out = out.replace(String.format("%%%s%%", k), o == null ? "null"
: o.toString());
}
this.out.print(out);
this.out.printf("\n");
if (autoflush)
this.out.flush();
argsPnP(args);
}
private Args argsPnP(Args args) {
if (args == null) {
if (argsStack.size() > 0)
args = argsStack.pop();
else
args = new Args();
args.put("prefix", prefix);
args.put("suffix", suffix);
return args;
} else {
args.clear();
argsStack.push(args);
return null;
}
}
private String toStringValue(Object o) {
if (o == null)
return "";
if (o instanceof String)
return "\"" + ((String) o).replace("\"", "\\\"");
else if (o.getClass().isArray()) {
StringBuilder buffer = new StringBuilder();
buffer.append("{");
for (int i = 0; i < Array.getLength(o); i++) {
if (i > 0)
buffer.append(", ");
buffer.append(toStringValue(Array.get(o, i)));
}
buffer.append("}");
return buffer.toString();
}
return o.toString();
}
/*
* (non-Javadoc)
*
* @see
* org.graphstream.stream.AttributeSink#edgeAttributeAdded(java.lang.String,
* long, java.lang.String, java.lang.String, java.lang.Object)
*/
public void edgeAttributeAdded(String sourceId, long timeId, String edgeId,
String attribute, Object value) {
Args args = argsPnP(null);
args.put("sourceId", sourceId);
args.put("timeId", timeId);
args.put("edgeId", edgeId);
args.put("attributeId", attribute);
args.put("value", toStringValue(value));
print(EventType.ADD_EDGE_ATTRIBUTE, args);
}
/*
* (non-Javadoc)
*
* @see
* org.graphstream.stream.AttributeSink#edgeAttributeChanged(java.lang.String
* , long, java.lang.String, java.lang.String, java.lang.Object,
* java.lang.Object)
*/
public void edgeAttributeChanged(String sourceId, long timeId,
String edgeId, String attribute, Object oldValue, Object newValue) {
Args args = argsPnP(null);
args.put("sourceId", sourceId);
args.put("timeId", timeId);
args.put("edgeId", edgeId);
args.put("attributeId", attribute);
args.put("value", toStringValue(newValue));
print(EventType.SET_EDGE_ATTRIBUTE, args);
}
/*
* (non-Javadoc)
*
* @see
* org.graphstream.stream.AttributeSink#edgeAttributeRemoved(java.lang.String
* , long, java.lang.String, java.lang.String)
*/
public void edgeAttributeRemoved(String sourceId, long timeId,
String edgeId, String attribute) {
Args args = argsPnP(null);
args.put("sourceId", sourceId);
args.put("timeId", timeId);
args.put("edgeId", edgeId);
args.put("attributeId", attribute);
print(EventType.DEL_EDGE_ATTRIBUTE, args);
}
/*
* (non-Javadoc)
*
* @see
* org.graphstream.stream.AttributeSink#graphAttributeAdded(java.lang.String
* , long, java.lang.String, java.lang.Object)
*/
public void graphAttributeAdded(String sourceId, long timeId,
String attribute, Object value) {
Args args = argsPnP(null);
args.put("sourceId", sourceId);
args.put("timeId", timeId);
args.put("attributeId", attribute);
args.put("value", toStringValue(value));
print(EventType.ADD_GRAPH_ATTRIBUTE, args);
}
/*
* (non-Javadoc)
*
* @see
* org.graphstream.stream.AttributeSink#graphAttributeChanged(java.lang.
* String, long, java.lang.String, java.lang.Object, java.lang.Object)
*/
public void graphAttributeChanged(String sourceId, long timeId,
String attribute, Object oldValue, Object newValue) {
Args args = argsPnP(null);
args.put("sourceId", sourceId);
args.put("timeId", timeId);
args.put("attributeId", attribute);
args.put("value", toStringValue(newValue));
print(EventType.SET_GRAPH_ATTRIBUTE, args);
}
/*
* (non-Javadoc)
*
* @see
* org.graphstream.stream.AttributeSink#graphAttributeRemoved(java.lang.
* String, long, java.lang.String)
*/
public void graphAttributeRemoved(String sourceId, long timeId,
String attribute) {
Args args = argsPnP(null);
args.put("sourceId", sourceId);
args.put("timeId", timeId);
args.put("attributeId", attribute);
print(EventType.DEL_GRAPH_ATTRIBUTE, args);
}
/*
* (non-Javadoc)
*
* @see
* org.graphstream.stream.AttributeSink#nodeAttributeAdded(java.lang.String,
* long, java.lang.String, java.lang.String, java.lang.Object)
*/
public void nodeAttributeAdded(String sourceId, long timeId, String nodeId,
String attribute, Object value) {
Args args = argsPnP(null);
args.put("sourceId", sourceId);
args.put("timeId", timeId);
args.put("nodeId", nodeId);
args.put("attributeId", attribute);
args.put("value", toStringValue(value));
print(EventType.ADD_NODE_ATTRIBUTE, args);
}
/*
* (non-Javadoc)
*
* @see
* org.graphstream.stream.AttributeSink#nodeAttributeChanged(java.lang.String
* , long, java.lang.String, java.lang.String, java.lang.Object,
* java.lang.Object)
*/
public void nodeAttributeChanged(String sourceId, long timeId,
String nodeId, String attribute, Object oldValue, Object newValue) {
Args args = argsPnP(null);
args.put("sourceId", sourceId);
args.put("timeId", timeId);
args.put("nodeId", nodeId);
args.put("attributeId", attribute);
args.put("value", toStringValue(newValue));
print(EventType.SET_NODE_ATTRIBUTE, args);
}
/*
* (non-Javadoc)
*
* @see
* org.graphstream.stream.AttributeSink#nodeAttributeRemoved(java.lang.String
* , long, java.lang.String, java.lang.String)
*/
public void nodeAttributeRemoved(String sourceId, long timeId,
String nodeId, String attribute) {
Args args = argsPnP(null);
args.put("sourceId", sourceId);
args.put("timeId", timeId);
args.put("nodeId", nodeId);
args.put("attributeId", attribute);
print(EventType.DEL_NODE_ATTRIBUTE, args);
}
/*
* (non-Javadoc)
*
* @see org.graphstream.stream.ElementSink#edgeAdded(java.lang.String, long,
* java.lang.String, java.lang.String, java.lang.String, boolean)
*/
public void edgeAdded(String sourceId, long timeId, String edgeId,
String fromNodeId, String toNodeId, boolean directed) {
Args args = argsPnP(null);
args.put("sourceId", sourceId);
args.put("timeId", timeId);
args.put("edgeId", edgeId);
args.put("source", fromNodeId);
args.put("target", toNodeId);
print(EventType.ADD_EDGE, args);
}
/*
* (non-Javadoc)
*
* @see org.graphstream.stream.ElementSink#edgeRemoved(java.lang.String,
* long, java.lang.String)
*/
public void edgeRemoved(String sourceId, long timeId, String edgeId) {
Args args = argsPnP(null);
args.put("sourceId", sourceId);
args.put("timeId", timeId);
args.put("edgeId", edgeId);
print(EventType.DEL_EDGE, args);
}
/*
* (non-Javadoc)
*
* @see org.graphstream.stream.ElementSink#graphCleared(java.lang.String,
* long)
*/
public void graphCleared(String sourceId, long timeId) {
Args args = argsPnP(null);
args.put("sourceId", sourceId);
args.put("timeId", timeId);
print(EventType.CLEAR, args);
}
/*
* (non-Javadoc)
*
* @see org.graphstream.stream.ElementSink#nodeAdded(java.lang.String, long,
* java.lang.String)
*/
public void nodeAdded(String sourceId, long timeId, String nodeId) {
Args args = argsPnP(null);
args.put("sourceId", sourceId);
args.put("timeId", timeId);
args.put("nodeId", nodeId);
print(EventType.ADD_NODE, args);
}
/*
* (non-Javadoc)
*
* @see org.graphstream.stream.ElementSink#nodeRemoved(java.lang.String,
* long, java.lang.String)
*/
public void nodeRemoved(String sourceId, long timeId, String nodeId) {
Args args = argsPnP(null);
args.put("sourceId", sourceId);
args.put("timeId", timeId);
args.put("nodeId", nodeId);
print(EventType.DEL_NODE, args);
}
/*
* (non-Javadoc)
*
* @see org.graphstream.stream.ElementSink#stepBegins(java.lang.String,
* long, double)
*/
public void stepBegins(String sourceId, long timeId, double step) {
Args args = argsPnP(null);
args.put("sourceId", sourceId);
args.put("timeId", timeId);
args.put("step", step);
print(EventType.STEP_BEGINS, args);
}
}