1 /*
2 * jDTAUS Core API
3 * Copyright (C) 2005 Christian Schulte
4 * <cs@schulte.it>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 */
21 package org.jdtaus.core.container;
22
23 import java.io.Serializable;
24 import java.util.Arrays;
25 import java.util.Collection;
26 import java.util.HashMap;
27 import java.util.Map;
28
29 /**
30 * Collection of dependencies.
31 *
32 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
33 * @version $JDTAUS: Dependencies.java 8743 2012-10-07 03:06:20Z schulte $
34 */
35 public class Dependencies extends ModelObject implements Cloneable, Serializable
36 {
37 //--Constants---------------------------------------------------------------
38
39 /** Serial version UID for backwards compatibility with 1.0.x classes. */
40 private static final long serialVersionUID = 4207539567564921413L;
41
42 //---------------------------------------------------------------Constants--
43 //--Dependencies------------------------------------------------------------
44
45 /**
46 * The dependencies held by the instance.
47 * @serial
48 */
49 private Dependency[] dependencies;
50
51 /**
52 * Maps dependency names to dependencies.
53 * @serial
54 */
55 private final Map names = new HashMap();
56
57 /**
58 * Hash code.
59 * @serial
60 */
61 private int hashCode;
62
63 /** Creates a new {@code Dependencies} instance. */
64 public Dependencies()
65 {
66 super();
67 }
68
69 /**
70 * Gets all dependencies of the collection.
71 *
72 * @return all dependencies of the collection.
73 */
74 public Dependency[] getDependencies()
75 {
76 if ( this.dependencies == null )
77 {
78 this.dependencies = new Dependency[ 0 ];
79 this.hashCode = 0;
80 }
81
82 return this.dependencies;
83 }
84
85 /**
86 * Setter for property {@code dependencies}.
87 *
88 * @param value the new dependencies for the collection.
89 *
90 * @throws DuplicateDependencyException if {@code value} contains duplicate
91 * dependencies.
92 */
93 public void setDependencies( final Dependency[] value )
94 {
95 this.names.clear();
96 this.hashCode = 0;
97 this.dependencies = null;
98
99 if ( value != null )
100 {
101 for ( int i = value.length - 1; i >= 0; i-- )
102 {
103 this.hashCode += value[i].hashCode();
104 if ( this.names.put( value[i].getName(), value[i] ) != null )
105 {
106 this.names.clear();
107 this.hashCode = 0;
108
109 throw new DuplicateDependencyException( value[i].getName() );
110 }
111
112 }
113
114 this.dependencies = value;
115 }
116 }
117
118 /**
119 * Gets a dependency for a name.
120 *
121 * @param name the name of the dependency to return.
122 *
123 * @return a reference to the dependency named {@code name}.
124 *
125 * @throws NullPointerException if {@code name} is {@code null}.
126 * @throws MissingDependencyException if no dependency matching {@code name}
127 * exists in the collection.
128 */
129 public Dependency getDependency( final String name )
130 {
131 if ( name == null )
132 {
133 throw new NullPointerException( "name" );
134 }
135
136 final Dependency ret = (Dependency) this.names.get( name );
137
138 if ( ret == null )
139 {
140 throw new MissingDependencyException( name );
141 }
142
143 return ret;
144 }
145
146 /**
147 * Gets a dependency for an index.
148 *
149 * @param index the index of the dependency to return.
150 *
151 * @return a reference to the dependency at {@code index}.
152 *
153 * @throws IndexOutOfBoundsException if {@code index} is negativ,
154 * greater than or equal to {@code size()}.
155 */
156 public final Dependency getDependency( final int index )
157 {
158 if ( index < 0 || index >= this.size() )
159 {
160 throw new ArrayIndexOutOfBoundsException( index );
161 }
162
163 return this.getDependencies()[index];
164 }
165
166 /**
167 * Gets the number of dependencies held by the instance.
168 *
169 * @return the number of dependencies held by the instance.
170 */
171 public final int size()
172 {
173 return this.getDependencies().length;
174 }
175
176 /**
177 * Creates a string representing the properties of the instance.
178 *
179 * @return a string representing the properties of the instance.
180 */
181 private String internalString()
182 {
183 final StringBuffer buf = new StringBuffer( 200 ).append( '{' );
184 buf.append( this.internalString( this ) );
185
186 final Dependency[] deps = this.getDependencies();
187 for ( int i = deps.length - 1; i >= 0; i-- )
188 {
189 buf.append( ", [" ).append( i ).append( "]=" ).
190 append( deps[i] );
191
192 }
193 buf.append( '}' );
194 return buf.toString();
195 }
196
197 //------------------------------------------------------------Dependencies--
198 //--Object------------------------------------------------------------------
199
200 /**
201 * Indicates whether some other object is equal to this one by comparing
202 * the values of all properties.
203 *
204 * @param o the reference object with which to compare.
205 *
206 * @return {@code true} if this object is the same as {@code o};
207 * {@code false} otherwise.
208 */
209 public boolean equals( final Object o )
210 {
211 boolean equal = this == o;
212
213 if ( !equal && o instanceof Dependencies )
214 {
215 final Dependencies that = (Dependencies) o;
216 final Collection these = Arrays.asList( this.getDependencies() );
217 final Collection those = Arrays.asList( that.getDependencies() );
218
219 equal = this.size() == that.size() && these.containsAll( those );
220 }
221
222 return equal;
223 }
224
225 /**
226 * Returns a hash code value for this object.
227 *
228 * @return a hash code value for this object.
229 */
230 public int hashCode()
231 {
232 return this.hashCode;
233 }
234
235 /**
236 * Returns a string representation of the object.
237 *
238 * @return a string representation of the object.
239 */
240 public String toString()
241 {
242 return super.toString() + this.internalString();
243 }
244
245 /**
246 * Creates and returns a deep copy of this object.
247 *
248 * @return a clone of this instance.
249 */
250 public Object clone()
251 {
252 try
253 {
254 final Dependencies ret = (Dependencies) super.clone();
255 final Dependency[] deps = this.getDependencies();
256 final Dependency[] cloned = new Dependency[ deps.length ];
257 for ( int i = deps.length - 1; i >= 0; i-- )
258 {
259 cloned[i] = (Dependency) deps[i].clone();
260 }
261
262 ret.setDependencies( cloned );
263 return ret;
264 }
265 catch ( final CloneNotSupportedException e )
266 {
267 throw new AssertionError( e );
268 }
269 }
270
271 //------------------------------------------------------------------Object--
272 }