github.com/gopherd/gonum@v0.0.4/graph/formats/gexf12/gexf.go (about)

     1  // Copyright ©2018 The Gonum Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Package gexf12 implements marshaling and unmarshaling of GEXF1.2 documents.
     6  //
     7  // For details of GEXF see https://gephi.org/gexf/format/.
     8  package gexf12 // import "github.com/gopherd/gonum/graph/formats/gexf12"
     9  
    10  import (
    11  	"bytes"
    12  	"encoding/xml"
    13  	"time"
    14  )
    15  
    16  // BUG(kortschak): The namespace for GEFX1.2 is 1.2draft, though it has
    17  // already been deprecated. There is no specification for 1.3, although
    18  // it is being used in the wild.
    19  
    20  // Content holds a GEFX graph and metadata.
    21  type Content struct {
    22  	XMLName xml.Name `xml:"http://www.gexf.net/1.2draft gexf"`
    23  	Meta    *Meta    `xml:"meta,omitempty"`
    24  	Graph   Graph    `xml:"graph"`
    25  	// Version must be "1.2".
    26  	Version string `xml:"version,attr"`
    27  	Variant string `xml:"variant,attr,omitempty"`
    28  }
    29  
    30  // Meta holds optional metadata associated with the graph.
    31  type Meta struct {
    32  	Creator      string    `xml:"creator,omitempty"`
    33  	Keywords     string    `xml:"keywords,omitempty"`
    34  	Description  string    `xml:"description,omitempty"`
    35  	LastModified time.Time `xml:"lastmodifieddate,attr,omitempty"`
    36  }
    37  
    38  // MarshalXML implements the xml.Marshaler interface.
    39  func (t *Meta) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
    40  	type T Meta
    41  	var layout struct {
    42  		*T
    43  		LastModified *xsdDate `xml:"lastmodifieddate,attr,omitempty"`
    44  	}
    45  	layout.T = (*T)(t)
    46  	layout.LastModified = (*xsdDate)(&layout.T.LastModified)
    47  	return e.EncodeElement(layout, start)
    48  }
    49  
    50  // UnmarshalXML implements the xml.Unmarshaler interface.
    51  func (t *Meta) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
    52  	type T Meta
    53  	var overlay struct {
    54  		*T
    55  		LastModified *xsdDate `xml:"lastmodifieddate,attr,omitempty"`
    56  	}
    57  	overlay.T = (*T)(t)
    58  	overlay.LastModified = (*xsdDate)(&overlay.T.LastModified)
    59  	return d.DecodeElement(&overlay, &start)
    60  }
    61  
    62  // Graph stores the graph nodes, edges, dynamics and visualization data.
    63  type Graph struct {
    64  	Attributes []Attributes `xml:"attributes"`
    65  	Nodes      Nodes        `xml:"nodes"`
    66  	Edges      Edges        `xml:"edges"`
    67  	// TimeFormat may be one of "integer", "double", "date" or "dateTime".
    68  	TimeFormat string `xml:"timeformat,attr,omitempty"`
    69  	Start      string `xml:"start,attr,omitempty"`
    70  	StartOpen  string `xml:"startopen,attr,omitempty"`
    71  	End        string `xml:"end,attr,omitempty"`
    72  	EndOpen    string `xml:"endopen,attr,omitempty"`
    73  	// DefaultEdgeType may be one of "directed", "undirected" or "mutual".
    74  	DefaultEdgeType string `xml:"defaultedgetype,attr,omitempty"`
    75  	// IDType may be one of "integer" or "string".
    76  	IDType string `xml:"idtype,attr,omitempty"`
    77  	// Mode may be "static" or "dynamic".
    78  	Mode string `xml:"mode,attr,omitempty"`
    79  }
    80  
    81  // Attributes holds a collection of potentially dynamic attributes
    82  // associated with a graph.
    83  type Attributes struct {
    84  	Attributes []Attribute `xml:"attribute,omitempty"`
    85  	// Class be one of "node" or "edge".
    86  	Class string `xml:"class,attr"`
    87  	// Mode may be "static" or "dynamic".
    88  	Mode      string `xml:"mode,attr,omitempty"`
    89  	Start     string `xml:"start,attr,omitempty"`
    90  	StartOpen string `xml:"startopen,attr,omitempty"`
    91  	End       string `xml:"end,attr,omitempty"`
    92  	EndOpen   string `xml:"endopen,attr,omitempty"`
    93  }
    94  
    95  // Attribute holds a single graph attribute.
    96  type Attribute struct {
    97  	ID    string `xml:"id,attr"`
    98  	Title string `xml:"title,attr"`
    99  	// Type may be one of "integer", "long", "double", "float",
   100  	// "boolean", "liststring", "string", or "anyURI".
   101  	Type    string `xml:"type,attr"`
   102  	Default string `xml:"default,omitempty"`
   103  	Options string `xml:"options,omitempty"`
   104  }
   105  
   106  // Nodes holds a collection of nodes constituting a graph or subgraph.
   107  type Nodes struct {
   108  	Count int    `xml:"count,attr,omitempty"`
   109  	Nodes []Node `xml:"node,omitempty"`
   110  }
   111  
   112  // Node is a single node and its associated attributes.
   113  type Node struct {
   114  	ID        string     `xml:"id,attr,omitempty"`
   115  	Label     string     `xml:"label,attr,omitempty"`
   116  	AttValues *AttValues `xml:"attvalues"`
   117  	Spells    *Spells    `xml:"spells"`
   118  	Nodes     *Nodes     `xml:"nodes"`
   119  	Edges     *Edges     `xml:"edges"`
   120  	ParentID  string     `xml:"pid,attr,omitempty"`
   121  	Parents   *Parents   `xml:"parents"`
   122  	Color     *Color     `xml:"http://www.gexf.net/1.2draft/viz color"`
   123  	Position  *Position  `xml:"http://www.gexf.net/1.2draft/viz position"`
   124  	Size      *Size      `xml:"http://www.gexf.net/1.2draft/viz size"`
   125  	Shape     *NodeShape `xml:"http://www.gexf.net/1.2draft/viz shape"`
   126  	Start     string     `xml:"start,attr,omitempty"`
   127  	StartOpen string     `xml:"startopen,attr,omitempty"`
   128  	End       string     `xml:"end,attr,omitempty"`
   129  	EndOpen   string     `xml:"endopen,attr,omitempty"`
   130  }
   131  
   132  // NodeShape holds the visual representation of a node with associated
   133  // dynamics.
   134  type NodeShape struct {
   135  	Spells *Spells `xml:"spells,omitempty"`
   136  	// Value be one of "disc", "square", "triangle",
   137  	// "diamond" or "image".
   138  	Shape     string `xml:"value,attr"`
   139  	URI       string `xml:"uri,attr,omitempty"`
   140  	Start     string `xml:"start,attr,omitempty"`
   141  	StartOpen string `xml:"startopen,attr,omitempty"`
   142  	End       string `xml:"end,attr,omitempty"`
   143  	EndOpen   string `xml:"endopen,attr,omitempty"`
   144  }
   145  
   146  // Color represents a node or edge color and its associated dynamics.
   147  type Color struct {
   148  	Spells    *Spells `xml:"spells,omitempty"`
   149  	R         byte    `xml:"r,attr"`
   150  	G         byte    `xml:"g,attr"`
   151  	B         byte    `xml:"b,attr"`
   152  	A         float64 `xml:"a,attr,omitempty"`
   153  	Start     string  `xml:"start,attr,omitempty"`
   154  	StartOpen string  `xml:"startopen,attr,omitempty"`
   155  	End       string  `xml:"end,attr,omitempty"`
   156  	EndOpen   string  `xml:"endopen,attr,omitempty"`
   157  }
   158  
   159  // Edges holds a collection of edges constituting a graph or subgraph.
   160  type Edges struct {
   161  	Count int    `xml:"count,attr,omitempty"`
   162  	Edges []Edge `xml:"edge,omitempty"`
   163  }
   164  
   165  // Edge is a single edge and its associated attributes.
   166  type Edge struct {
   167  	ID        string     `xml:"id,attr,omitempty"`
   168  	AttValues *AttValues `xml:"attvalues"`
   169  	Spells    *Spells    `xml:"spells"`
   170  	Color     *Color     `xml:"http://www.gexf.net/1.2draft/viz color"`
   171  	Thickness *Thickness `xml:"http://www.gexf.net/1.2draft/viz thickness"`
   172  	Shape     *Edgeshape `xml:"http://www.gexf.net/1.2draft/viz shape"`
   173  	Start     string     `xml:"start,attr,omitempty"`
   174  	StartOpen string     `xml:"startopen,attr,omitempty"`
   175  	End       string     `xml:"end,attr,omitempty"`
   176  	EndOpen   string     `xml:"endopen,attr,omitempty"`
   177  	// Type may be one of directed, undirected, mutual
   178  	Type   string  `xml:"type,attr,omitempty"`
   179  	Label  string  `xml:"label,attr,omitempty"`
   180  	Source string  `xml:"source,attr"`
   181  	Target string  `xml:"target,attr"`
   182  	Weight float64 `xml:"weight,attr,omitempty"`
   183  }
   184  
   185  // AttVlues holds a collection of attribute values.
   186  type AttValues struct {
   187  	AttValues []AttValue `xml:"attvalue,omitempty"`
   188  }
   189  
   190  // AttValues holds a single attribute value and its associated dynamics.
   191  type AttValue struct {
   192  	For       string `xml:"for,attr"`
   193  	Value     string `xml:"value,attr"`
   194  	Start     string `xml:"start,attr,omitempty"`
   195  	StartOpen string `xml:"startopen,attr,omitempty"`
   196  	End       string `xml:"end,attr,omitempty"`
   197  	EndOpen   string `xml:"endopen,attr,omitempty"`
   198  }
   199  
   200  // EdgeShape holds the visual representation of an edge with associated
   201  // dynamics.
   202  type Edgeshape struct {
   203  	// Shape be one of solid, dotted, dashed, double
   204  	Shape     string  `xml:"value,attr"`
   205  	Spells    *Spells `xml:"spells,omitempty"`
   206  	Start     string  `xml:"start,attr,omitempty"`
   207  	StartOpen string  `xml:"startopen,attr,omitempty"`
   208  	End       string  `xml:"end,attr,omitempty"`
   209  	EndOpen   string  `xml:"endopen,attr,omitempty"`
   210  }
   211  
   212  // Parents holds parent relationships between nodes in a hierarchical
   213  // graph.
   214  type Parents struct {
   215  	Parents []Parent `xml:"parent,omitempty"`
   216  }
   217  
   218  // Parent is a single parent relationship.
   219  type Parent struct {
   220  	For string `xml:"for,attr"`
   221  }
   222  
   223  // Position hold the spatial position of a node and its dynamics.
   224  type Position struct {
   225  	X         float64 `xml:"x,attr"`
   226  	Y         float64 `xml:"y,attr"`
   227  	Z         float64 `xml:"z,attr"`
   228  	Spells    *Spells `xml:"spells,omitempty"`
   229  	Start     string  `xml:"start,attr,omitempty"`
   230  	StartOpen string  `xml:"startopen,attr,omitempty"`
   231  	End       string  `xml:"end,attr,omitempty"`
   232  	EndOpen   string  `xml:"endopen,attr,omitempty"`
   233  }
   234  
   235  // Size hold the visual size of a node and its dynamics.
   236  type Size struct {
   237  	Value     float64 `xml:"value,attr"`
   238  	Spells    *Spells `xml:"http://www.gexf.net/1.2draft/viz spells,omitempty"`
   239  	Start     string  `xml:"start,attr,omitempty"`
   240  	StartOpen string  `xml:"startopen,attr,omitempty"`
   241  	End       string  `xml:"end,attr,omitempty"`
   242  	EndOpen   string  `xml:"endopen,attr,omitempty"`
   243  }
   244  
   245  // Thickness hold the visual thickness of an edge and its dynamics.
   246  type Thickness struct {
   247  	Value     float64 `xml:"value,attr"`
   248  	Spells    *Spells `xml:"http://www.gexf.net/1.2draft/viz spells,omitempty"`
   249  	Start     string  `xml:"start,attr,omitempty"`
   250  	StartOpen string  `xml:"startopen,attr,omitempty"`
   251  	End       string  `xml:"end,attr,omitempty"`
   252  	EndOpen   string  `xml:"endopen,attr,omitempty"`
   253  }
   254  
   255  // Spells holds a collection of time dynamics for a graph entity.
   256  type Spells struct {
   257  	Spells []Spell `xml:"spell"`
   258  }
   259  
   260  // Spell is a time interval.
   261  type Spell struct {
   262  	Start     string `xml:"start,attr,omitempty"`
   263  	StartOpen string `xml:"startopen,attr,omitempty"`
   264  	End       string `xml:"end,attr,omitempty"`
   265  	EndOpen   string `xml:"endopen,attr,omitempty"`
   266  }
   267  
   268  type xsdDate time.Time
   269  
   270  func (t *xsdDate) UnmarshalText(text []byte) error {
   271  	return _unmarshalTime(text, (*time.Time)(t), "2006-01-02")
   272  }
   273  
   274  func (t xsdDate) MarshalText() ([]byte, error) {
   275  	return []byte((time.Time)(t).Format("2006-01-02")), nil
   276  }
   277  
   278  func (t xsdDate) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
   279  	if (time.Time)(t).IsZero() {
   280  		return nil
   281  	}
   282  	m, err := t.MarshalText()
   283  	if err != nil {
   284  		return err
   285  	}
   286  	return e.EncodeElement(m, start)
   287  }
   288  
   289  func (t xsdDate) MarshalXMLAttr(name xml.Name) (xml.Attr, error) {
   290  	if (time.Time)(t).IsZero() {
   291  		return xml.Attr{}, nil
   292  	}
   293  	m, err := t.MarshalText()
   294  	return xml.Attr{Name: name, Value: string(m)}, err
   295  }
   296  
   297  func _unmarshalTime(text []byte, t *time.Time, format string) (err error) {
   298  	s := string(bytes.TrimSpace(text))
   299  	*t, err = time.Parse(format, s)
   300  	if _, ok := err.(*time.ParseError); ok {
   301  		*t, err = time.Parse(format+"Z07:00", s)
   302  	}
   303  	return err
   304  }