View Javadoc

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  
19  package org.itracker.model;
20  
21  import java.io.Serializable;
22  import java.util.Comparator;
23  
24  import org.apache.commons.lang.builder.CompareToBuilder;
25  import org.apache.commons.lang.builder.ToStringBuilder;
26  
27  /**
28   * Models a project component.
29   * 
30   * <p>
31   * A Component is a project subdivision, like a sub-project or functional area,
32   * ... <br>
33   * It is identified by a unique name within the project to which it belongs
34   * (composition). <br>
35   * e.g.: core, web-ui, swing-ui, help, ...
36   * </p>
37   * 
38   * <p>
39   * A component cannot have sub-components, unlike categories and sub-categories
40   * that exist in some issue tracking systems.
41   * </p>
42   * 
43   * @author Jason
44   * @author Johnny
45   */
46  public class Component extends AbstractEntity implements Comparable<Entity> {
47  
48  	/**
49  	 * 
50  	 */
51  	private static final long serialVersionUID = 1L;
52  
53  	public static final Comparator<Component> NAME_COMPARATOR = new NameComparator();
54  	public static final Comparator<Component> PROJECTNAME_COMPARATOR = new ProjectNameComparator();
55  
56  	/**
57  	 * Project to which this component belongs. Invariant: never <tt>null</tt>.
58  	 */
59  
60  	private Project project;
61  
62  	/**
63  	 * Unique name identifying this component within its project. Invariant:
64  	 * never <tt>null</tt>.
65  	 */
66  	private String name;
67  
68  	/** Component description. */
69  	private String description;
70  
71  	/**
72  	 * Component status.
73  	 * <p>
74  	 * Invariant: never <tt>null</tt>.
75  	 * </p>
76  	 */
77  	private Status status;
78  
79  	/*
80  	 * This class used to have a <code>issues</code> attribute, which was a
81  	 * Collection<Issue>. This has been removed because the association
82  	 * Component - Issue doesn't need to be navigatable in this direction.
83  	 */
84  
85  	/**
86  	 * Default constructor (required by Hibernate).
87  	 * 
88  	 * <p>
89  	 * PENDING: should be <code>private</code> so that it can only be used by
90  	 * Hibernate, to ensure that <code>project</code> and <code>name</code>,
91  	 * which form an instance's identity, are never <tt>null</tt>.
92  	 * </p>
93  	 */
94  	public Component() {
95  	}
96  
97  	/**
98  	 * Creates a new active Component of the given name for the given Project.
99  	 * 
100 	 * @param project
101 	 *            owning this component
102 	 * @param name
103 	 *            unique component name within the project
104 	 */
105 	public Component(Project project, String name) {
106 		setProject(project);
107 		setName(name);
108 
109 		// A new component is active by default.
110 		this.status = Status.ACTIVE;
111 	}
112 
113 	/**
114 	 * Returns the project owning this component.
115 	 * 
116 	 * @return parent project
117 	 */
118 	public Project getProject() {
119 		return project;
120 	}
121 
122 	/**
123 	 * Sets the project owning this component.
124 	 * 
125 	 * <p>
126 	 * PENDING: The project shouldn't be modified because it is part of a
127 	 * component's natural key and is used in the equals method!
128 	 * </p>
129 	 * 
130 	 * @param project
131 	 *            parent project
132 	 * @throws IllegalArgumentException
133 	 *             null project
134 	 */
135 	public void setProject(Project project) {
136 		if (project == null) {
137 			throw new IllegalArgumentException("null project");
138 		}
139 		this.project = project;
140 	}
141 
142 	/**
143 	 * Returns this component's name.
144 	 * 
145 	 * @return unique name within the parent project
146 	 */
147 	public String getName() {
148 		return name;
149 	}
150 
151 	/**
152 	 * Sets this component's name.
153 	 * 
154 	 * <p>
155 	 * PENDING: The name shouldn't be modified because it is part of a
156 	 * component's natural key and is used in the equals method!
157 	 * </p>
158 	 * 
159 	 * @param name
160 	 *            unique name within the parent project
161 	 * @throws IllegalArgumentException
162 	 *             null name
163 	 */
164 	public void setName(String name) {
165 		if (name == null) {
166 			throw new IllegalArgumentException("null name");
167 		}
168 		this.name = name;
169 	}
170 
171 	/**
172 	 * Returns this component's description.
173 	 * 
174 	 * @return description
175 	 */
176 	public String getDescription() {
177 		return description;
178 	}
179 
180 	/**
181 	 * Sets this component's description.
182 	 * 
183 	 * @param description
184 	 *            description
185 	 */
186 	public void setDescription(String description) {
187 		this.description = description;
188 	}
189 
190 	/**
191 	 * Returns this component's status.
192 	 * 
193 	 * @return enum value
194 	 */
195 	public Status getStatus() {
196 		return status;
197 	}
198 
199 	/**
200 	 * Sets this component's status.
201 	 * 
202 	 * @param status
203 	 *            enum value
204 	 * @throws IllegalArgumentException
205 	 *             <code>status</code> is <tt>null</tt>
206 	 */
207 	public void setStatus(Status status) {
208 		if (status == null) {
209 			throw new IllegalArgumentException("null status");
210 		}
211 		this.status = status;
212 	}
213 
214 	// /**
215 	// * Two component instances are equal if they belong to the same project
216 	// * and have the same name.
217 	// */
218 	// @Override
219 	// public boolean equals(Object obj) {
220 	// if (this == obj) {
221 	// return true;
222 	// }
223 	//        
224 	// if (obj instanceof Component) {
225 	// final Component other = (Component)obj;
226 	//            
227 	// return this.project.equals(other.project)
228 	// && this.name.equals(other.name);
229 	// }
230 	// return false;
231 	// }
232 
233 	// /**
234 	// * Overridden to match implementation of method {@link #equals(Object)}.
235 	// */
236 	// @Override
237 	// public int hashCode() {
238 	// return this.project.hashCode() + this.name.hashCode();
239 	// }
240 
241 	/**
242 	 * Returns contatanation of system ID and object natural key.
243 	 * 
244 	 * @return <tt>Component [id=this.id, project=this.project, name=this.name]</tt>
245 	 */
246 	@Override
247 	public String toString() {
248 		return new ToStringBuilder(this).append("id", getId()).append("project",
249 				getProject()).append("name", getName()).toString();
250 	}
251 
252 	// /**
253 	// * Compares 2 Components by project and name (natural key).
254 	// */
255 	// public int compareTo(Component other) {
256 	//    	
257 	// final int projectComparison = this.project.compareTo(other.project);
258 	//        
259 	// if (projectComparison == 0) {
260 	// return this.name.compareTo(other.name);
261 	// }
262 	// return projectComparison;
263 	// }
264 	//    
265 
266 	/**
267 	 * Compares 2 Components by name.
268 	 * 
269 	 * <p>
270 	 * It should only be used to compare components of the same project, because
271 	 * it doesn't take the project into account.
272 	 * </p>
273 	 */
274 	private static class NameComparator implements Comparator<Component>, Serializable {
275 
276 		/**
277 		 * 
278 		 */
279 		private static final long serialVersionUID = 1L;
280 
281 		public int compare(Component a, Component b) {
282 			return new CompareToBuilder().append(a.getName(), b.getName()).append(a.getId(), b.getId()).toComparison();
283 
284 		}
285 
286 	}
287 
288 	public static final class ProjectNameComparator implements
289 			Comparator<Component>, Serializable {
290 		/**
291 		 * 
292 		 */
293 		private static final long serialVersionUID = 1L;
294 
295 		public int compare(Component o1, Component o2) {
296 			if (null != o1.getProject() && null != o2.getProject()) {
297 				return new CompareToBuilder().append(o1.getProject().getName(), o2.getProject().getName())
298 					.append(o1.getName(), o2.getName()).toComparison();
299 			}
300 			return NAME_COMPARATOR.compare(o1, o2);
301 		}
302 	}
303 
304 }