001 /*
002 * jDTAUS Core API
003 * Copyright (c) 2005 Christian Schulte
004 *
005 * Christian Schulte, Haldener Strasse 72, 58095 Hagen, Germany
006 * <schulte2005@users.sourceforge.net> (+49 2331 3543887)
007 *
008 * This library is free software; you can redistribute it and/or
009 * modify it under the terms of the GNU Lesser General Public
010 * License as published by the Free Software Foundation; either
011 * version 2.1 of the License, or any later version.
012 *
013 * This library is distributed in the hope that it will be useful,
014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
016 * Lesser General Public License for more details.
017 *
018 * You should have received a copy of the GNU Lesser General Public
019 * License along with this library; if not, write to the Free Software
020 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
021 *
022 */
023 package org.jdtaus.core.container;
024
025 import java.io.Serializable;
026 import java.util.Arrays;
027 import java.util.Collection;
028 import java.util.HashMap;
029 import java.util.Map;
030
031 /**
032 * Collection of dependencies.
033 *
034 * @author <a href="mailto:schulte2005@users.sourceforge.net">Christian Schulte</a>
035 * @version $Id: Dependencies.java 8044 2009-07-02 01:29:05Z schulte2005 $
036 */
037 public class Dependencies extends ModelObject implements Cloneable, Serializable
038 {
039 //--Constants---------------------------------------------------------------
040
041 /** Serial version UID for backwards compatibility with 1.0.x classes. */
042 private static final long serialVersionUID = 4207539567564921413L;
043
044 //---------------------------------------------------------------Constants--
045 //--Dependencies------------------------------------------------------------
046
047 /**
048 * The dependencies held by the instance.
049 * @serial
050 */
051 private Dependency[] dependencies;
052
053 /**
054 * Maps dependency names to dependencies.
055 * @serial
056 */
057 private final Map names = new HashMap();
058
059 /**
060 * Hash code.
061 * @serial
062 */
063 private int hashCode;
064
065 /**
066 * Gets all dependencies of the collection.
067 *
068 * @return all dependencies of the collection.
069 */
070 public Dependency[] getDependencies()
071 {
072 if ( this.dependencies == null )
073 {
074 this.dependencies = new Dependency[ 0 ];
075 this.hashCode = 0;
076 }
077
078 return this.dependencies;
079 }
080
081 /**
082 * Setter for property {@code dependencies}.
083 *
084 * @param value the new dependencies for the collection.
085 *
086 * @throws DuplicateDependencyException if {@code value} contains duplicate
087 * dependencies.
088 */
089 public void setDependencies( final Dependency[] value )
090 {
091 this.names.clear();
092 this.hashCode = 0;
093 this.dependencies = null;
094
095 if ( value != null )
096 {
097 for ( int i = value.length - 1; i >= 0; i-- )
098 {
099 this.hashCode += value[i].hashCode();
100 if ( this.names.put( value[i].getName(), value[i] ) != null )
101 {
102 this.names.clear();
103 this.hashCode = 0;
104
105 throw new DuplicateDependencyException( value[i].getName() );
106 }
107
108 }
109
110 this.dependencies = value;
111 }
112 }
113
114 /**
115 * Gets a dependency for a name.
116 *
117 * @param name the name of the dependency to return.
118 *
119 * @return a reference to the dependency named {@code name}.
120 *
121 * @throws NullPointerException if {@code name} is {@code null}.
122 * @throws MissingDependencyException if no dependency matching {@code name}
123 * exists in the collection.
124 */
125 public Dependency getDependency( final String name )
126 {
127 if ( name == null )
128 {
129 throw new NullPointerException( "name" );
130 }
131
132 final Dependency ret = (Dependency) this.names.get( name );
133
134 if ( ret == null )
135 {
136 throw new MissingDependencyException( name );
137 }
138
139 return ret;
140 }
141
142 /**
143 * Gets a dependency for an index.
144 *
145 * @param index the index of the dependency to return.
146 *
147 * @return a reference to the dependency at {@code index}.
148 *
149 * @throws IndexOutOfBoundsException if {@code index} is negativ,
150 * greater than or equal to {@code size()}.
151 */
152 public final Dependency getDependency( final int index )
153 {
154 if ( index < 0 || index >= this.size() )
155 {
156 throw new ArrayIndexOutOfBoundsException( index );
157 }
158
159 return this.getDependencies()[index];
160 }
161
162 /**
163 * Gets the number of dependencies held by the instance.
164 *
165 * @return the number of dependencies held by the instance.
166 */
167 public final int size()
168 {
169 return this.getDependencies().length;
170 }
171
172 /**
173 * Creates a string representing the properties of the instance.
174 *
175 * @return a string representing the properties of the instance.
176 */
177 private String internalString()
178 {
179 final StringBuffer buf = new StringBuffer( 200 ).append( '{' );
180 buf.append( this.internalString( this ) );
181
182 final Dependency[] deps = this.getDependencies();
183 for ( int i = deps.length - 1; i >= 0; i-- )
184 {
185 buf.append( ", [" ).append( i ).append( "]=" ).
186 append( deps[i] );
187
188 }
189 buf.append( '}' );
190 return buf.toString();
191 }
192
193 //------------------------------------------------------------Dependencies--
194 //--Object------------------------------------------------------------------
195
196 /**
197 * Indicates whether some other object is equal to this one by comparing
198 * the values of all properties.
199 *
200 * @param o the reference object with which to compare.
201 *
202 * @return {@code true} if this object is the same as {@code o};
203 * {@code false} otherwise.
204 */
205 public boolean equals( final Object o )
206 {
207 boolean equal = this == o;
208
209 if ( !equal && o instanceof Dependencies )
210 {
211 final Dependencies that = (Dependencies) o;
212 final Collection these = Arrays.asList( this.getDependencies() );
213 final Collection those = Arrays.asList( that.getDependencies() );
214
215 equal = this.size() == that.size() && these.containsAll( those );
216 }
217
218 return equal;
219 }
220
221 /**
222 * Returns a hash code value for this object.
223 *
224 * @return a hash code value for this object.
225 */
226 public int hashCode()
227 {
228 return this.hashCode;
229 }
230
231 /**
232 * Returns a string representation of the object.
233 *
234 * @return a string representation of the object.
235 */
236 public String toString()
237 {
238 return super.toString() + this.internalString();
239 }
240
241 /**
242 * Creates and returns a deep copy of this object.
243 *
244 * @return a clone of this instance.
245 */
246 public Object clone()
247 {
248 try
249 {
250 final Dependencies ret = (Dependencies) super.clone();
251 final Dependency[] deps = this.getDependencies();
252 final Dependency[] cloned = new Dependency[ deps.length ];
253 for ( int i = deps.length - 1; i >= 0; i-- )
254 {
255 cloned[i] = (Dependency) deps[i].clone();
256 }
257
258 ret.setDependencies( cloned );
259 return ret;
260 }
261 catch ( CloneNotSupportedException e )
262 {
263 throw new AssertionError( e );
264 }
265 }
266
267 //------------------------------------------------------------------Object--
268 }