Component.java
/*
* This software was designed and created by Jason Carroll.
* Copyright (c) 2002, 2003, 2004 Jason Carroll.
* The author can be reached at jcarroll@cowsultants.com
* ITracker website: http://www.cowsultants.com
* ITracker forums: http://www.cowsultants.com/phpBB/index.php
*
* This program is free software; you can redistribute it and/or modify
* it only under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
package org.itracker.model;
import org.apache.commons.lang.builder.CompareToBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;
import java.io.Serializable;
import java.util.Comparator;
/**
* Models a project component.
* <p/>
* <p>
* A Component is a project subdivision, like a sub-project or functional area,
* ... <br>
* It is identified by a unique name within the project to which it belongs
* (composition). <br>
* e.g.: core, web-ui, swing-ui, help, ...
* </p>
* <p/>
* <p>
* A component cannot have sub-components, unlike categories and sub-categories
* that exist in some issue tracking systems.
* </p>
*
* @author Jason
* @author Johnny
*/
public class Component extends AbstractEntity implements Comparable<Entity> {
/**
*
*/
private static final long serialVersionUID = 1L;
public static final Comparator<Component> NAME_COMPARATOR = new NameComparator();
public static final Comparator<Component> PROJECTNAME_COMPARATOR = new ProjectNameComparator();
/**
* Project to which this component belongs. Invariant: never <tt>null</tt>.
*/
private Project project;
/**
* Unique name identifying this component within its project. Invariant:
* never <tt>null</tt>.
*/
private String name;
/**
* Component description.
*/
private String description;
/**
* Component status.
* <p>
* Invariant: never <tt>null</tt>.
* </p>
*/
private Status status;
/*
* This class used to have a <code>issues</code> attribute, which was a
* Collection<Issue>. This has been removed because the association
* Component - Issue doesn't need to be navigatable in this direction.
*/
/**
* Default constructor (required by Hibernate).
* <p/>
* <p>
* PENDING: should be <code>private</code> so that it can only be used by
* Hibernate, to ensure that <code>project</code> and <code>name</code>,
* which form an instance's identity, are never <tt>null</tt>.
* </p>
*/
public Component() {
}
/**
* Creates a new active Component of the given name for the given Project.
*
* @param project owning this component
* @param name unique component name within the project
*/
public Component(Project project, String name) {
setProject(project);
setName(name);
// A new component is active by default.
this.status = Status.ACTIVE;
}
/**
* Returns the project owning this component.
*
* @return parent project
*/
public Project getProject() {
return project;
}
/**
* Sets the project owning this component.
* <p/>
* <p>
* PENDING: The project shouldn't be modified because it is part of a
* component's natural key and is used in the equals method!
* </p>
*
* @param project parent project
* @throws IllegalArgumentException null project
*/
public void setProject(Project project) {
if (project == null) {
throw new IllegalArgumentException("null project");
}
this.project = project;
}
/**
* Returns this component's name.
*
* @return unique name within the parent project
*/
public String getName() {
return name;
}
/**
* Sets this component's name.
* <p/>
* <p>
* PENDING: The name shouldn't be modified because it is part of a
* component's natural key and is used in the equals method!
* </p>
*
* @param name unique name within the parent project
* @throws IllegalArgumentException null name
*/
public void setName(String name) {
if (name == null) {
throw new IllegalArgumentException("null name");
}
this.name = name;
}
/**
* Returns this component's description.
*
* @return description
*/
public String getDescription() {
return description;
}
/**
* Sets this component's description.
*
* @param description description
*/
public void setDescription(String description) {
this.description = description;
}
/**
* Returns this component's status.
*
* @return enum value
*/
public Status getStatus() {
return status;
}
/**
* Sets this component's status.
*
* @param status enum value
* @throws IllegalArgumentException <code>status</code> is <tt>null</tt>
*/
public void setStatus(Status status) {
if (status == null) {
throw new IllegalArgumentException("null status");
}
this.status = status;
}
// /**
// * Two component instances are equal if they belong to the same project
// * and have the same name.
// */
// @Override
// public boolean equals(Object obj) {
// if (this == obj) {
// return true;
// }
//
// if (obj instanceof Component) {
// final Component other = (Component)obj;
//
// return this.project.equals(other.project)
// && this.name.equals(other.name);
// }
// return false;
// }
// /**
// * Overridden to match implementation of method {@link #equals(Object)}.
// */
// @Override
// public int hashCode() {
// return this.project.hashCode() + this.name.hashCode();
// }
/**
* Returns contatanation of system ID and object natural key.
*
* @return <tt>Component [id=this.id, project=this.project, name=this.name]</tt>
*/
@Override
public String toString() {
return new ToStringBuilder(this).append("id", getId()).append("project",
getProject()).append("name", getName()).toString();
}
// /**
// * Compares 2 Components by project and name (natural key).
// */
// public int compareTo(Component other) {
//
// final int projectComparison = this.project.compareTo(other.project);
//
// if (projectComparison == 0) {
// return this.name.compareTo(other.name);
// }
// return projectComparison;
// }
//
/**
* Compares 2 Components by name.
* <p/>
* <p>
* It should only be used to compare components of the same project, because
* it doesn't take the project into account.
* </p>
*/
private static class NameComparator implements Comparator<Component>, Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
public int compare(Component a, Component b) {
return new CompareToBuilder().append(a.getName(), b.getName()).append(a.getId(), b.getId()).toComparison();
}
}
public static final class ProjectNameComparator implements
Comparator<Component>, Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
public int compare(Component o1, Component o2) {
if (null != o1.getProject() && null != o2.getProject()) {
return new CompareToBuilder().append(o1.getProject().getName(), o2.getProject().getName())
.append(o1.getName(), o2.getName()).toComparison();
}
return NAME_COMPARATOR.compare(o1, o2);
}
}
}