Component.java

  1. /*
  2.  * This software was designed and created by Jason Carroll.
  3.  * Copyright (c) 2002, 2003, 2004 Jason Carroll.
  4.  * The author can be reached at jcarroll@cowsultants.com
  5.  * ITracker website: http://www.cowsultants.com
  6.  * ITracker forums: http://www.cowsultants.com/phpBB/index.php
  7.  *
  8.  * This program is free software; you can redistribute it and/or modify
  9.  * it only under the terms of the GNU General Public License as published by
  10.  * the Free Software Foundation; either version 2 of the License, or
  11.  * (at your option) any later version.
  12.  *
  13.  * This program is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  * GNU General Public License for more details.
  17.  */

  18. package org.itracker.model;

  19. import org.apache.commons.lang.builder.CompareToBuilder;
  20. import org.apache.commons.lang.builder.ToStringBuilder;

  21. import java.io.Serializable;
  22. import java.util.Comparator;

  23. /**
  24.  * Models a project component.
  25.  * <p/>
  26.  * <p>
  27.  * A Component is a project subdivision, like a sub-project or functional area,
  28.  * ... <br>
  29.  * It is identified by a unique name within the project to which it belongs
  30.  * (composition). <br>
  31.  * e.g.: core, web-ui, swing-ui, help, ...
  32.  * </p>
  33.  * <p/>
  34.  * <p>
  35.  * A component cannot have sub-components, unlike categories and sub-categories
  36.  * that exist in some issue tracking systems.
  37.  * </p>
  38.  *
  39.  * @author Jason
  40.  * @author Johnny
  41.  */
  42. public class Component extends AbstractEntity implements Comparable<Entity> {

  43.     /**
  44.      *
  45.      */
  46.     private static final long serialVersionUID = 1L;

  47.     public static final Comparator<Component> NAME_COMPARATOR = new NameComparator();
  48.     public static final Comparator<Component> PROJECTNAME_COMPARATOR = new ProjectNameComparator();

  49.     /**
  50.      * Project to which this component belongs. Invariant: never <tt>null</tt>.
  51.      */

  52.     private Project project;

  53.     /**
  54.      * Unique name identifying this component within its project. Invariant:
  55.      * never <tt>null</tt>.
  56.      */
  57.     private String name;

  58.     /**
  59.      * Component description.
  60.      */
  61.     private String description;

  62.     /**
  63.      * Component status.
  64.      * <p>
  65.      * Invariant: never <tt>null</tt>.
  66.      * </p>
  67.      */
  68.     private Status status;

  69.     /*
  70.       * This class used to have a <code>issues</code> attribute, which was a
  71.       * Collection<Issue>. This has been removed because the association
  72.       * Component - Issue doesn't need to be navigatable in this direction.
  73.       */

  74.     /**
  75.      * Default constructor (required by Hibernate).
  76.      * <p/>
  77.      * <p>
  78.      * PENDING: should be <code>private</code> so that it can only be used by
  79.      * Hibernate, to ensure that <code>project</code> and <code>name</code>,
  80.      * which form an instance's identity, are never <tt>null</tt>.
  81.      * </p>
  82.      */
  83.     public Component() {
  84.     }

  85.     /**
  86.      * Creates a new active Component of the given name for the given Project.
  87.      *
  88.      * @param project owning this component
  89.      * @param name    unique component name within the project
  90.      */
  91.     public Component(Project project, String name) {
  92.         setProject(project);
  93.         setName(name);

  94.         // A new component is active by default.
  95.         this.status = Status.ACTIVE;
  96.     }

  97.     /**
  98.      * Returns the project owning this component.
  99.      *
  100.      * @return parent project
  101.      */
  102.     public Project getProject() {
  103.         return project;
  104.     }

  105.     /**
  106.      * Sets the project owning this component.
  107.      * <p/>
  108.      * <p>
  109.      * PENDING: The project shouldn't be modified because it is part of a
  110.      * component's natural key and is used in the equals method!
  111.      * </p>
  112.      *
  113.      * @param project parent project
  114.      * @throws IllegalArgumentException null project
  115.      */
  116.     public void setProject(Project project) {
  117.         if (project == null) {
  118.             throw new IllegalArgumentException("null project");
  119.         }
  120.         this.project = project;
  121.     }

  122.     /**
  123.      * Returns this component's name.
  124.      *
  125.      * @return unique name within the parent project
  126.      */
  127.     public String getName() {
  128.         return name;
  129.     }

  130.     /**
  131.      * Sets this component's name.
  132.      * <p/>
  133.      * <p>
  134.      * PENDING: The name shouldn't be modified because it is part of a
  135.      * component's natural key and is used in the equals method!
  136.      * </p>
  137.      *
  138.      * @param name unique name within the parent project
  139.      * @throws IllegalArgumentException null name
  140.      */
  141.     public void setName(String name) {
  142.         if (name == null) {
  143.             throw new IllegalArgumentException("null name");
  144.         }
  145.         this.name = name;
  146.     }

  147.     /**
  148.      * Returns this component's description.
  149.      *
  150.      * @return description
  151.      */
  152.     public String getDescription() {
  153.         return description;
  154.     }

  155.     /**
  156.      * Sets this component's description.
  157.      *
  158.      * @param description description
  159.      */
  160.     public void setDescription(String description) {
  161.         this.description = description;
  162.     }

  163.     /**
  164.      * Returns this component's status.
  165.      *
  166.      * @return enum value
  167.      */
  168.     public Status getStatus() {
  169.         return status;
  170.     }

  171.     /**
  172.      * Sets this component's status.
  173.      *
  174.      * @param status enum value
  175.      * @throws IllegalArgumentException <code>status</code> is <tt>null</tt>
  176.      */
  177.     public void setStatus(Status status) {
  178.         if (status == null) {
  179.             throw new IllegalArgumentException("null status");
  180.         }
  181.         this.status = status;
  182.     }

  183.     // /**
  184.     // * Two component instances are equal if they belong to the same project
  185.     // * and have the same name.
  186.     // */
  187.     // @Override
  188.     // public boolean equals(Object obj) {
  189.     // if (this == obj) {
  190.     // return true;
  191.     // }
  192.     //
  193.     // if (obj instanceof Component) {
  194.     // final Component other = (Component)obj;
  195.     //
  196.     // return this.project.equals(other.project)
  197.     // && this.name.equals(other.name);
  198.     // }
  199.     // return false;
  200.     // }

  201.     // /**
  202.     // * Overridden to match implementation of method {@link #equals(Object)}.
  203.     // */
  204.     // @Override
  205.     // public int hashCode() {
  206.     // return this.project.hashCode() + this.name.hashCode();
  207.     // }

  208.     /**
  209.      * Returns contatanation of system ID and object natural key.
  210.      *
  211.      * @return <tt>Component [id=this.id, project=this.project, name=this.name]</tt>
  212.      */
  213.     @Override
  214.     public String toString() {
  215.         return new ToStringBuilder(this).append("id", getId()).append("project",
  216.                 getProject()).append("name", getName()).toString();
  217.     }

  218.     // /**
  219.     // * Compares 2 Components by project and name (natural key).
  220.     // */
  221.     // public int compareTo(Component other) {
  222.     //
  223.     // final int projectComparison = this.project.compareTo(other.project);
  224.     //
  225.     // if (projectComparison == 0) {
  226.     // return this.name.compareTo(other.name);
  227.     // }
  228.     // return projectComparison;
  229.     // }
  230.     //

  231.     /**
  232.      * Compares 2 Components by name.
  233.      * <p/>
  234.      * <p>
  235.      * It should only be used to compare components of the same project, because
  236.      * it doesn't take the project into account.
  237.      * </p>
  238.      */
  239.     private static class NameComparator implements Comparator<Component>, Serializable {

  240.         /**
  241.          *
  242.          */
  243.         private static final long serialVersionUID = 1L;

  244.         public int compare(Component a, Component b) {
  245.             return new CompareToBuilder().append(a.getName(), b.getName()).append(a.getId(), b.getId()).toComparison();

  246.         }

  247.     }

  248.     public static final class ProjectNameComparator implements
  249.             Comparator<Component>, Serializable {
  250.         /**
  251.          *
  252.          */
  253.         private static final long serialVersionUID = 1L;

  254.         public int compare(Component o1, Component o2) {
  255.             if (null != o1.getProject() && null != o2.getProject()) {
  256.                 return new CompareToBuilder().append(o1.getProject().getName(), o2.getProject().getName())
  257.                         .append(o1.getName(), o2.getName()).toComparison();
  258.             }
  259.             return NAME_COMPARATOR.compare(o1, o2);
  260.         }
  261.     }

  262. }