GraphModel.java
package org.thewonderlemming.c4plantuml.graphml.model;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import org.thewonderlemming.c4plantuml.graphml.Build;
import org.thewonderlemming.c4plantuml.graphml.model.builder.WithDirection;
import org.thewonderlemming.c4plantuml.graphml.model.builder.WithId;
/**
* The <graph> part of the representation of a GraphML stream.
* <p>
* It is based on JAXB.
*
* @author thewonderlemming
*
*/
@XmlRootElement(name = GraphModel.TAG_NAME)
@XmlAccessorType(XmlAccessType.FIELD)
public class GraphModel {
/**
* The current model XML tag name.
*/
public static final String TAG_NAME = "graph";
@XmlAttribute(name = "edgedefault", required = true)
private String edgeDefault;
@XmlAttribute(name = "id", required = true)
private String id;
@XmlElement(name = DataModel.TAG_NAME)
private MappedListDecorator<DataModel, String> seq1Data;
@XmlElement(name = NodeModel.TAG_NAME)
private MappedListDecorator<NodeModel, String> seq2Nodes;
@XmlElement(name = EdgeModel.TAG_NAME)
private MappedListDecorator<EdgeModel, String> seq3Edges;
/**
* A builder to the current {@link GraphModel} class.
*
* @return a new {@link GraphModel} instance.
*/
public static WithId<String, WithDirection<WithData<WithNodes<WithEdges<Build<GraphModel>>>>>> builder() {
return id -> edgeDefault -> data -> nodes -> edges -> () -> {
final GraphModel graph = new GraphModel();
graph.setId(id);
graph.setEdgeDefault(edgeDefault);
graph.setData(data);
graph.setNodes(nodes);
graph.setEdges(edges);
return graph;
};
}
/**
* Default constructor.
*/
private GraphModel() {
// Does nothing but hiding the current constructor.
}
/**
* Adds the given {@link DataModel} to the list if its {@link DataModel#getKey()} is not already there or replaces
* it else.
*
* @param data the given {@link DataModel} to add/replace.
*/
public void addOrReplaceData(final DataModel data) {
this.seq1Data.addOrReplaceData(data);
}
/**
* Adds the given {@link EdgeModel} to the list if its {@link EdgeModel#getId()} is not already there or replaces
* it else.
*
* @param edge the given {@link EdgeModel} to add/replace.
*/
public void addOrReplaceEdge(final EdgeModel edge) {
this.seq3Edges.addOrReplaceData(edge);
}
/**
* Adds the given {@link NodeModel} to the list if its {@link NodeModel#getId()} is not already there or replaces
* it else.
*
* @param node the given {@link NodeModel} to add/replace.
*/
public void addOrReplaceNode(final NodeModel node) {
this.seq2Nodes.addOrReplaceData(node);
}
/**
* Returns the current graph's properties list.
*
* @return the {@link DataModel} list.
*/
public List<DataModel> getData() {
return seq1Data;
}
/**
* Returns the graph's <edgedefault> property.
*
* @return the <edgedefault> property.
*/
public String getEdgeDefault() {
return edgeDefault;
}
/**
* Returns the graph's edges as a list.
*
* @return the graph {@link EdgeModel} list.
*/
public List<EdgeModel> getEdges() {
return seq3Edges;
}
/**
* Returns the graph ID.
*
* @return the graph ID.
*/
public String getId() {
return id;
}
/**
* Returns the graph(s nodes as a list.
*
* @return the graph {@link NodeModel} list.
*/
public List<NodeModel> getNodes() {
return seq2Nodes;
}
/**
* Tells whether or not the current graph is a child of a node (or if it stands alone).
*
* @param node the {@link NodeModel} that is supposed to be the the parent node.
* @return {@code true} if the graph is a child of the given {@code node}, {@code false} else.
*/
public boolean isChildOfNode(final NodeModel node) {
return this.id.equals(node.getId() + "::");
}
/**
* Tells whether or not the current graph is empty.
*
* @return {@code true} if the graph is empty, {@code false} else.
*/
public boolean isEmpty() {
return this.seq1Data.isEmpty() && this.seq2Nodes.isEmpty() && this.seq3Edges.isEmpty();
}
/**
* Tells whether or not the current graph is not empty.
*
* @return {@code true} if the graph is not empty, {@code false} else.
*/
public boolean isNotEmpty() {
return !this.isEmpty();
}
/**
* Sets the graph's aspect.
*
* @param aspect the graph {@code aspect}.
*/
public void setAspect(final String aspect) {
this
.addOrReplaceData(DataModel
.builder()
.withKey(C4Keys.ASPECT)
.withValue(aspect)
.build());
}
/**
* Sets the graph's ID.
*
* @param id the graph {@code id}
*/
public void setId(final String id) {
this.id = id;
}
/**
* Sets a <data> tag of type {@link C4Keys#TITLE} and with the given value.
*
* @param title the data value to set.
*/
public void setTitle(final String title) {
this
.addOrReplaceData(DataModel
.builder()
.withKey(C4Keys.TITLE)
.withValue(title)
.build());
}
private void setData(final List<DataModel> data) {
this.seq1Data = new MappedListDecorator<>(DataModel.class, data, DataModel::getKey);
}
private void setEdgeDefault(final String edgeDefault) {
this.edgeDefault = edgeDefault;
}
private void setEdges(final List<EdgeModel> edges) {
this.seq3Edges = new MappedListDecorator<>(EdgeModel.class, edges, EdgeModel::getId);
}
private void setNodes(final List<NodeModel> nodes) {
this.seq2Nodes = new MappedListDecorator<>(NodeModel.class, nodes, NodeModel::getId);
}
}