# NodeModel.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.WithId;

    /**
     * The &lt;node&gt; part of the representation of a GraphML stream.
     * <p>
     * It is based on JAXB.
     *
     * @author thewonderlemming
     *
     */
    @XmlRootElement(name = NodeModel.TAG_NAME)
    @XmlAccessorType(XmlAccessType.FIELD)
    public class NodeModel {

        /**
         * The current model XML tag name.
         */
        public static final String TAG_NAME = "node";

        @XmlAttribute(name = "id", required = true)
        private String id;

        @XmlElement(name = DataModel.TAG_NAME, required = true)
        private MappedListDecorator<DataModel, String> seq1Data;

        @XmlElement(name = GraphModel.TAG_NAME)
        private GraphModel seq2Graph;

        /**
         * A builder to the current {@link NodeModel} class.
         *
         * @return a new {@link NodeModel} instance.
         */
        public static WithId<String, WithData<Build<NodeModel>>> builder() {

            return id -> data -> () -> {

                final NodeModel node = new NodeModel();
                node.setId(id);
                node.setData(data);

                return node;
            };
        }

        /**
         * Default constructor.
         */
        private NodeModel() {
            // 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);
        }

        /**
         * Returns the current &lt;node&gt; data tags.
         *
         * @return the node data tags.
         */
        public List<DataModel> getData() {
            return seq1Data;
        }

        /**
         * Returns the current &lt;node&gt; inner graph.
         *
         * @return the node inner graph.
         */
        public GraphModel getGraph() {
            return seq2Graph;
        }

        /**
         * Returns the current &lt;node&gt; ID.
         *
         * @return the node ID.
         */
        public String getId() {
            return id;
        }

        /**
         * Sets a &lt;data&gt; tag of type {@link C4Keys#DESCRIPTION} and with the given value.
         *
         * @param description the data value to set.
         */
        public void setDescription(final String description) {
            this.seq1Data
                .add(DataModel
                    .builder()
                        .withKey(C4Keys.DESCRIPTION)
                        .withValue(description)
                        .build());
        }

        /**
         * Sets a &lt;data&gt; tag of type {@link C4Keys#ENTITY_TYPE} and with the given value.
         *
         * @param entityType the data value to set.
         */
        public void setEntityType(final EntityType entityType) {
            this.seq1Data
                .add(DataModel
                    .builder()
                        .withKey(C4Keys.ENTITY_TYPE)
                        .withValue(entityType.getTypeAsString())
                        .build());
        }

        /**
         * Sets a child &lt;graph&gt; into the current &lt;node&gt;.
         *
         * @param graph the graph to set.
         */
        public void setGraph(final GraphModel graph) {
            this.seq2Graph = graph;
        }

        /**
         * Sets the current &lt;node&gt; {@code id} attribute.
         *
         * @param id the id to set.
         */
        public void setId(final String id) {
            this.id = id;
        }

        /**
         * Sets a &lt;data&gt; tag of type {@link C4Keys#NAME} and with the given value.
         *
         * @param name the data value to set.
         */
        public void setName(final String name) {
            this.seq1Data
                .add(DataModel
                    .builder()
                        .withKey(C4Keys.NAME)
                        .withValue(name)
                        .build());
        }

        /**
         * Sets a &lt;data&gt; tag of type {@link C4Keys#TECHNOLOGICAL_STACK} and with the given value.
         *
         * @param technologicalStack the data value to set.
         */
        public void setTechnologicalStack(final String technologicalStack) {
            this.seq1Data
                .add(DataModel
                    .builder()
                        .withKey(C4Keys.TECHNOLOGICAL_STACK)
                        .withValue(technologicalStack)
                        .build());
        }

        private void setData(final List<DataModel> data) {
            this.seq1Data = new MappedListDecorator<>(DataModel.class, data, DataModel::getKey);
        }
    }