/* * #%L * Nazgul Project: nazgul-core-algorithms-tree-model * %% * Copyright (C) 2010 - 2017 jGuru Europe AB * %% * Licensed under the jGuru Europe AB license (the "License"), based * on Apache License, Version 2.0; you may not use this file except * in compliance with the License. * * You may obtain a copy of the License at * * http://www.jguru.se/licenses/jguruCorporateSourceLicense-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * #L% * */ package se.jguru.nazgul.core.algorithms.tree.model.node; import se.jguru.nazgul.core.algorithms.api.trees.node.Node; import se.jguru.nazgul.core.xmlbinding.api.XmlBinder; import se.jguru.nazgul.tools.validation.api.exception.InternalStateValidationException; import javax.persistence.Access; import javax.persistence.AccessType; import javax.persistence.Basic; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.OneToMany; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlType; import java.util.ArrayList; import java.util.List; /** * An implementation of the AbstractStringKeyNode which uses Strings as values. * * @author <a href="mailto:lj@jguru.se">Lennart Jörelid</a>, jGuru Europe AB */ @Entity @Access(AccessType.FIELD) @XmlType(namespace = XmlBinder.CORE_NAMESPACE, propOrder = {"data", "children"}) @XmlAccessorType(XmlAccessType.FIELD) public class StringNode extends AbstractStringKeyNode<String> { // Internal state @Basic(optional = true) @Column(nullable = true) @XmlElement(nillable = true, required = false) private String data; @XmlElementWrapper(name = "children", nillable = true, required = false) @XmlElement(name = "child") @OneToMany(mappedBy = "parent", cascade = {CascadeType.PERSIST, CascadeType.REFRESH, CascadeType.MERGE}) /*@JoinTable(name = "nodes_children", joinColumns = @JoinColumn(name = "node_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "child_id", referencedColumnName = "id")) */ private List<StringNode> children; /** * JPA/JAXB-friendly constructor. */ public StringNode() { } /** * Convenience constructor creating a StringNode wrapping the supplied * data and sporting an empty List of children. * * @param key The nonempty key of this StringNode. * @param data The value of this StringNode. May be null. * @param parent The parent StringNode of this one. May be null only if this is a Root node. */ public StringNode(final String key, final String data, final StringNode parent) { this(key, data, parent, new ArrayList<StringNode>()); } /** * Compound constructor creating a StringNode wrapping the supplied data. * * @param key The nonempty key of this StringNode. * @param data The value of this StringNode. May be null. * @param parent The parent StringNode of this one. May be null only if this is a Root node. * @param children The children of this StringNode. May be empty but not null. */ public StringNode(final String key, final String data, final StringNode parent, final List<StringNode> children) { super(key, parent); // Assign internal state this.data = data; this.children = children; } /** * {@inheritDoc} */ @Override public <X extends Node<String, String>> List<X> getChildren() { return (List<X>) children; } /** * {@inheritDoc} */ @Override public String getData() { return data; } /** * {@inheritDoc} */ @Override public int compareTo(final Node<String, String> that) { int toReturn = super.compareTo(that); if (toReturn == 0) { if (getData() != null) { toReturn = getData().compareTo(that.getData()); } else if (that.getData() != null) { toReturn = 1; } } if (toReturn == 0) { // Simply check the number of children; // Don't perform a recursive analysis. toReturn = getChildren().size() - that.getChildren().size(); } // All done. return toReturn; } /** * {@inheritDoc} */ @Override protected void validateEntityState() throws InternalStateValidationException { // First, delegate. super.validateEntityState(); // The children set may be empty but not null. InternalStateValidationException.create() .notNull(children, "children") .endExpressionAndValidate(); } }