Transfer of additional information between server and client
Applies to: yFiles FLEX 1.2, yFiles FLEX 1.1, yFiles FLEX 1.0 print article email article

Type: Tips & Tricks

This article shows how to transfer additional data of simple type mapped to items as edges, nodes, graph, etc. between server and client.

It is often necessary to transfer data which is not part of the default implementation between server and client, additional information to influence the layout or the visual representation of the graph and its elements, for instance.
For simple data types like String, int, double, etc., the following steps are necessary:

Server (yFiles Java)

On the server side, the attribute has to be registered for reading and writing with the
com.yworks.yfiles.server.graphml.support.GraphRoundtripSupport, using GraphRoundtripSupport.addMapper(Object tag, String name, int graphMLType, int graphMLScope);
With the parameters:
  • tag: the provider Key to get the DataMap from the graph using Graph.getDataProvider(Object key);
  • name: the name for the data used in the GraphML file
  • graphMLType: an integer constant describing the type of the attribute, as defined in
    org.graphdrawing.graphml.attr.AttributeConstants
  • graphMLScope: an integer constant describing the scope (e.g. node, edge), as defined in
    org.graphdrawing.graphml.GraphMLConstants
GraphRoundtripSupport grs = new GraphRoundtripSupport();
    
// create a mapper with the tag "edgeProviderKey" 
// which will write int data for edges into attributes named "edgeIndex"
grs.addMapper("edgeProviderKey", "edgeIndex", AttributeConstants.TYPE_INT, GraphMLConstants.SCOPE_EDGE);
    
// get the LayoutGraph created by the GraphRoundtripSupport
LayoutGraph graph = grs.createRoundtripGraph();
    
// get the DataProvider with the tag "edgeProviderKey"
DataMap dp = (DataMap) graph.getDataProvider("edgeProviderKey");
    
// fill the Map with edge related data (here as example the index of the edge)
for (EdgeCursor ec = graph.edges(); ec.ok(); ec.next()) {
  Edge edge = ec.edge();
  dp.setInt(edge, edge.index());
}
// send the graph to the client
grs.sendGraph(graph, httpServletResponse);

Server (yFiles.NET)

On the server side, the attribute has to be registered for reading and writing with the yWorks.yFiles.Graph.Web.GraphRoundtripSupport, using
  • GraphRoundtripSupport.AddMapper<K, V>(object tag, string name) or
  • GraphRoundtripSupport.AddMapper<K, V>(object tag, string name, KeyScope scopeType, KeyType keyType)
The type argument K corresponds to the type to store the attribute for (mostly INode or IEdge). The type argument V corresponds to the type of the values to be stored (mostly string). The following parameters are required:
  • tag: The tag that is to be used to retrieve the mapper from the graph's mapper registry
  • name: The name of the attribute that is to be used for GraphML I/O
The scopeType and keyType parameters can either be passed explicitly or they will be inferred from the type attributes K and V. The following example registers a custom mapper for edge attributes, sets the mapper values and sends the graph to the client.
GraphRoundtripSupport roundtripSupport = createRoundtripSupport();

// create a mapper with the tag "edgeProviderKey" 
// that will write int data for edges into attributes named "edgeIndex"
roundtripSupport.AddMapper<IEdge,string>("edgeProviderKey", "edgeIndex");

// get the properly configured IGraph created by the GraphRoundtripSupport      
IGraph graph = roundtripSupport.CreateRoundtripGraph();
      
// retrieve the IMapper instance and register some data
IMapperRegistry registry = graph.Lookup(typeof(IMapperRegistry)) as IMapperRegistry;
if (null != registry) {
  IMapper<IEdge, string> edgeIndexMapper = registry.GetMapper<IEdge,string>("edgeProviderKey");
  if( null != edgeIndexMapper ) {
    int i = 0;
    foreach( IEdge edge in graph.Edges ) {
      edgeIndexMapper.SetValue( edge, i++.ToString() );
    }
  }
}

// send the graph to the client
roundtripSupport.SendGraph(graph,context.Response);

Client

A GraphML file containing custom mapped data will look like this:

 xmlns:xalan="http://xml.apache.org/xslt"><graphml>
  ...
  <!-- The custom GraphML attribute -->
  <key id="d0" for="edge" attr.name="edgeIndex" attr.type="int"/>
  
  <graph id="G" edgedefault="directed">
    ...
    <!-- An edge that has a <data> element referring to the GraphML attribute "d0" -->
    <edge id="e0">
	...
      <data key="d0">0</data>	<!-- The transferred value is 0 -->
    </edge>
    ...
  </graph>
</graphml>

On the client side, the attribute has to be registered with the RoundtripHandler, using
RoundtripHandler.addMapperAttribute(tag:Object, name:String = null, scope:String = GraphMLConstants.SCOPE_NODE, contentType:String = GraphMLConstants.TYPE_STRING). The parameters are the same as on the server side:
  • tag: the provider Key
  • name: the name for the data used in the GraphML file
  • scope: a String constant describing the scope (e.g. node, edge), as defined in com.yworks.io.graphml.GraphMLConstants
  • contentType: a String constant describing the type of the attribute, as defined in com.yworks.io.graphml.GraphMLConstants

The corresponding mapper has to be registered with the graph's mapper registry before the graphml data is read into the graph instance.

The following code reads the above GraphML file:

var graph:DefaultGraph = DefaultGraph(graphCanvas.graph);
			
// register the mapper for the attribute to the graph
graph.mapperRegistry.addMapper( "clientEdgeProviderKey", new DictionaryMapper() );
			
var roundtripHandler:RoundtripHandler = new RoundtripHandler(graphCanvas);
		
// register the mapper for the attribute to the RoundtripHandler
roundtripHandler.addMapperAttribute(
			"clientEdgeProviderKey",
			"edgeIndex", 
			GraphMLConstants.SCOPE_NODE, 
			GraphMLConstants.TYPE_INT);
		...
// let the roundtripHandler read the data here
		...
// get the mapper						
var dataMapper:IMapper = DefaultGraph( graphCanvas.graph ).mapperRegistry.getMapper( "clientEdgeProviderKey" );
		
// read the data from the mapper
var mappedEdgeData:int = dataMapper.lookupValue(anEdge);

Note
The same mechanism also works for sending from the client to the server.
See also yFiles FLEX Developer's guide, Chapter 3, Customizing the yFiles FLEX I/O Support.
Note
The RoundtripHandler can only handle simple attributes, as String, long, int, float, double and boolean. In order to transfer objects, one has to implement his own input handler (see yFiles FLEX Developer's guide, Chapter 3, Customizing the yFiles FLEX I/O Support)

Keywords: Client - Server - Communication - GraphML - Attributes - AttributeMapper

Provide feedback:
How useful was this article?    less 1 2 3 4 5 more
Email address (optional):
COPYRIGHT © 2008 yWorks · ALL RIGHTS RESERVED imprint | top | home