/*
* YouTestit source code:
* ======================
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
http://www.apache.org/licenses/LICENSE-2.0
*
* 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.
*
* Links:
* ======
* Homepage : http://www.youtestit.org
* Git : https://github.com/youtestit
*/
package org.youtestit.datamodel.entity;
import static javax.persistence.FetchType.LAZY;
import static org.youtestit.commons.utils.constants.Constants.DOCUMENT_PART;
import static org.youtestit.commons.utils.constants.Constants.ITEM_CLOSE;
import static org.youtestit.commons.utils.constants.Constants.ITEM_OPEN;
import static org.youtestit.commons.utils.constants.Constants.NULL_OBJ;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import org.youtestit.commons.utils.exceptions.entities.DependencyAssociationException;
/**
* The Dependency entity allow to persist all dependancies. The dependancies
* resolver must be a Digital Assets Management resolver. Dependancies graph
* it's a web of nodes and not a tree. This model is better for cron jobs
* modelisation. Be careful, we mus't have a cyclic dependancies.
*
* <pre>
* °
* parents ° children
* <---------------- ° ------------------->
* °
* °
* .---. °
* | A |----. °
* '---' | ° .---.
* | ° .--->| D |
* .---. | .---------. | '---'
* | B |-------->| Current |----.
* '---' | '---------' | .---.
* | ° '--->| E |
* .---. | ° '---'
* | C |----' °
* '---' °
* °
* °
* </pre>
*
* @author "<a href='mailto:patrickguillerm@gmail.com'>Patrick Guillerm</a>"
* @since Jan 10, 2012
*/
@Entity
public class Dependency implements Serializable {
// =========================================================================
// ATTRIBUTES
// =========================================================================
/** The Constant serialVersionUID. */
private static final long serialVersionUID = 6748704693494054253L;
/** The name. */
@Id
@GeneratedValue
private long uid;
/** The document. */
@ManyToOne(cascade = CascadeType.REMOVE)
@JoinColumn(name = "document_id", nullable = true, updatable = false)
private Document document;
/** The parents. */
@OneToMany(cascade = {CascadeType.REMOVE,CascadeType.PERSIST}, targetEntity = Dependency.class, orphanRemoval = true)
@JoinColumn(name = "parents_uid", nullable = true)
private List<Dependency> parents = new ArrayList<Dependency>();
/** The children. */
@OneToMany(cascade = {CascadeType.REMOVE,CascadeType.PERSIST}, targetEntity = Dependency.class, orphanRemoval = true)
@JoinColumn(name = "children_uid", nullable = true)
private List<Dependency> children = new ArrayList<Dependency>();
/** attribut to force waitting parent dependancies done*/
@Basic(fetch = LAZY)
private boolean mustWaitting;
// =========================================================================
// CONSTRUCTORS
// =========================================================================
/**
* Instantiates a new Dependency.
*/
public Dependency() {
super();
}
/**
* Instantiates a new dependency.
*
* @param document the document
*/
public Dependency(final Document document) {
super();
this.document = document;
}
/**
* Instantiates a new Dependency.
*
* @param document the document
* @param parents the parents
* @param children the children
*/
public Dependency(final Document document, final List<Dependency> parents, final List<Dependency> children) {
super();
this.document = document;
this.parents = parents;
this.children = children;
}
/**
* Instantiates a new Dependency for unit test.
*
* @param uid the uid
* @param document the document
* @param parents the parents
* @param children the children
*/
protected Dependency(final long uid, final Document document, final List<Dependency> parents,
final List<Dependency> children) {
super();
this.uid = uid;
this.document = document;
this.parents = parents;
this.children = children;
}
// =========================================================================
// METHODS
// =========================================================================
/**
* Adds the parent.
*
* @param dependency the dependency
* @throws DependencyAssociationException the dependancy association
* exception
*/
public void addParent(final Dependency dependency) throws DependencyAssociationException {
if (dependency != null) {
if (children.contains(dependency)) {
throw new DependencyAssociationException();
}
parents.add(dependency);
}
}
/**
* Removes the parent.
*
* @param dependency the dependency
*/
public void removeParent(final Dependency dependency) {
if (parents != null && dependency != null && parents.contains(dependency)) {
parents.remove(dependency);
}
}
/**
* Adds the child.
*
* @param dependency the dependency
* @throws DependencyAssociationException the dependancy association
* exception
*/
public void addChild(final Dependency dependency) throws DependencyAssociationException {
if (dependency != null) {
if (parents.contains(dependency)) {
throw new DependencyAssociationException();
}
children.add(dependency);
}
}
/**
* Removes the child.
*
* @param dependency the dependency
*/
public void removeChild(final Dependency dependency) {
if (children != null && dependency != null && children.contains(dependency)) {
children.remove(dependency);
}
}
/**
* Allow to check cyclic dependancies. For example a dependency can't be in
* parent and in children dependencies. This methods check that.
*
* @param current the list where no one dependencies do add must be contain.
* @param dependenciesToAdd the dependencies to add
* @throws DependencyAssociationException if one cyclic dependency find
*/
protected void checkDependencies(final List<Dependency> current, final List<Dependency> dependenciesToAdd)
throws DependencyAssociationException {
if (current != null && dependenciesToAdd != null) {
for (Dependency item : dependenciesToAdd) {
if (current.contains(item)) {
throw new DependencyAssociationException();
}
}
}
}
// =========================================================================
// OVERRIDES
// =========================================================================
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
final int prime = 31;
final int nbBytes = 32;
int result = 1;
result = prime * result + (int) (uid ^ (uid >>> nbBytes));
return result;
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object obj) {
boolean result = false;
if (this == obj) {
result = true;
}
if (obj != null && getClass() == obj.getClass()) {
final Dependency other = (Dependency) obj;
result = uid == other.uid;
}
return result;
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
final StringBuilder result = new StringBuilder("Dependency [");
result.append("uid=" + uid);
result.append("mustWaitting=" + mustWaitting);
result.append(renderDocumentToString());
result.append(renderListDependencies(", parents=", parents));
result.append(renderListDependencies(", children=", children));
return result.toString();
}
/**
* Render document to string.
*
* @return the string
*/
private String renderDocumentToString() {
final StringBuilder result = new StringBuilder();
result.append("document=");
if (document == null) {
result.append(NULL_OBJ);
} else {
result.append(document.getUid());
result.append(DOCUMENT_PART);
result.append(document.getTitle());
}
return result.toString();
}
/**
* Render list dependancies.
*
* @param name the property name
* @param depandancies the list of Dependency
* @return the render
*/
private String renderListDependencies(final String name, final List<Dependency> depandancies) {
final StringBuilder result = new StringBuilder();
result.append(name);
if (depandancies == null) {
result.append(NULL_OBJ);
} else {
result.append(ITEM_OPEN);
for (Dependency item : depandancies) {
result.append(item.uid);
if (item.getDocument() != null) {
result.append(DOCUMENT_PART);
result.append(document.getUid());
result.append(DOCUMENT_PART);
result.append(document.getTitle());
}
}
result.append(ITEM_CLOSE);
}
return result.toString();
}
// =========================================================================
// GETTERS & SETTERS
// =========================================================================
/**
* Gets the uid.
*
* @return the uid
*/
public long getUid() {
return uid;
}
/**
* Sets the uid.
*
* @param uid the new uid
*/
public void setUid(long uid) {
this.uid = uid;
}
/**
* Gets the document.
*
* @return the document
*/
public Document getDocument() {
return document;
}
/**
* Sets the document.
*
* @param document the new document
*/
public void setDocument(Document document) {
this.document = document;
}
/**
* Gets the parents.
*
* @return the parents
*/
public List<Dependency> getParents() {
return parents;
}
/**
* Sets the parents.
*
* @param parents the new parents
* @throws DependencyAssociationException if one cyclic dependency find
*/
public void setParents(List<Dependency> parents) throws DependencyAssociationException {
checkDependencies(children, parents);
this.parents = parents;
if (this.parents == null) {
this.parents = new ArrayList<Dependency>();
}
}
/**
* Gets the children.
*
* @return the children
*/
public List<Dependency> getChildren() {
return children;
}
/**
* Sets the children.
*
* @param children the new children
* @throws DependencyAssociationException if one cyclic dependency find
*/
public void setChildren(List<Dependency> children) throws DependencyAssociationException {
checkDependencies(parents, children);
this.children = children;
if (this.children == null) {
this.children = new ArrayList<Dependency>();
}
}
/**
* Checks if is must waitting.
*
* @return true, if is must waitting
*/
public boolean isMustWaitting() {
return mustWaitting;
}
/**
* Sets the must waitting.
*
* @param mustWaitting the new must waitting
*/
public void setMustWaitting(boolean mustWaitting) {
this.mustWaitting = mustWaitting;
}
}