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 arguments.
033 *
034 * @author <a href="mailto:schulte2005@users.sourceforge.net">Christian Schulte</a>
035 * @version $Id: Arguments.java 8044 2009-07-02 01:29:05Z schulte2005 $
036 */
037 public class Arguments extends ModelObject
038 implements Cloneable, Serializable
039 {
040 //--Constants---------------------------------------------------------------
041
042 /** Serial version UID for backwards compatibility with 1.5.x classes. */
043 private static final long serialVersionUID = -36607029931578091L;
044
045 //---------------------------------------------------------------Constants--
046 //--Arguments---------------------------------------------------------------
047
048 /**
049 * The arguments of the collection.
050 * @serial
051 */
052 private Argument[] arguments;
053
054 /**
055 * Maps argument names to arguments.
056 * @serial
057 */
058 private final Map names = new HashMap();
059
060 /**
061 * Hash code.
062 * @serial
063 */
064 private int hashCode;
065
066 /**
067 * Gets the arguments of the collection.
068 *
069 * @return the arguments of the collection.
070 */
071 public Argument[] getArguments()
072 {
073 if ( this.arguments == null )
074 {
075 this.arguments = new Argument[ 0 ];
076 this.hashCode = 0;
077 }
078
079 return this.arguments;
080 }
081
082 /**
083 * Setter for property {@code arguments}.
084 *
085 * @param value the new arguments for the instance.
086 *
087 * @throws DuplicateArgumentException if {@code value} contains
088 * duplicate arguments.
089 */
090 public void setArguments( final Argument[] value )
091 {
092 this.names.clear();
093 this.hashCode = 0;
094 this.arguments = null;
095
096 if ( value != null )
097 {
098 for ( int i = 0; i < value.length; i++ )
099 {
100 this.hashCode += value[i].hashCode();
101 if ( this.names.put( value[i].getName(), value[i] ) != null )
102 {
103 this.names.clear();
104 this.hashCode = 0;
105
106 throw new DuplicateArgumentException( value[i].getName() );
107 }
108 }
109
110 this.arguments = value;
111 }
112 }
113
114 /**
115 * Gets an argument for a name.
116 *
117 * @param name the name of the argument to return.
118 *
119 * @return a reference to the argument with name {@code name}.
120 *
121 * @throws NullPointerException if {@code name} is {@code null}.
122 * @throws MissingArgumentException if no argument matching {@code name}
123 * exists in the collection.
124 */
125 public Argument getArgument( final String name )
126 {
127 if ( name == null )
128 {
129 throw new NullPointerException( "name" );
130 }
131
132 final Argument ret = (Argument) this.names.get( name );
133
134 if ( ret == null )
135 {
136 throw new MissingArgumentException( name );
137 }
138
139 return ret;
140 }
141
142 /**
143 * Gets an argument for an index.
144 *
145 * @param index the index of the argument to return.
146 *
147 * @return a reference to the argument at {@code index}.
148 *
149 * @throws IndexOutOfBoundsException if {@code index} is negativ,
150 * greater than or equal to {@code size()}.
151 */
152 public final Argument getArgument( final int index )
153 {
154 if ( index < 0 || index >= this.size() )
155 {
156 throw new ArrayIndexOutOfBoundsException( index );
157 }
158
159 return this.getArguments()[index];
160 }
161
162 /**
163 * Gets the number of arguments held by the instance.
164 *
165 * @return the number of arguments held by the instance.
166 */
167 public final int size()
168 {
169 return this.getArguments().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 Argument[] args = this.getArguments();
183 for ( int i = args.length - 1; i >= 0; i-- )
184 {
185 buf.append( ", [" ).append( i ).append( "]=" ).
186 append( args[i] );
187
188 }
189
190 buf.append( '}' );
191 return buf.toString();
192 }
193
194 //----------------------------------------------------------Specifications--
195 //--Object------------------------------------------------------------------
196
197 /**
198 * Indicates whether some other object is equal to this one by comparing
199 * the values of all properties.
200 *
201 * @param o the reference object with which to compare.
202 *
203 * @return {@code true} if this object is the same as {@code o};
204 * {@code false} otherwise.
205 */
206 public boolean equals( final Object o )
207 {
208 boolean equal = this == o;
209
210 if ( !equal && o instanceof Arguments )
211 {
212 final Arguments that = (Arguments) o;
213 final Collection these = Arrays.asList( this.getArguments() );
214 final Collection those = Arrays.asList( that.getArguments() );
215
216 equal = this.size() == that.size() && these.containsAll( those );
217 }
218
219 return equal;
220 }
221
222 /**
223 * Returns a hash code value for this object.
224 *
225 * @return a hash code value for this object.
226 */
227 public int hashCode()
228 {
229 return this.hashCode;
230 }
231
232 /**
233 * Returns a string representation of the object.
234 *
235 * @return a string representation of the object.
236 */
237 public String toString()
238 {
239 return super.toString() + this.internalString();
240 }
241
242 /**
243 * Creates and returns a deep copy of this object.
244 *
245 * @return a clone of this instance.
246 */
247 public Object clone()
248 {
249 try
250 {
251 final Arguments ret = (Arguments) super.clone();
252 final Argument[] args = this.getArguments();
253 final Argument[] cloned = new Argument[ args.length ];
254
255 for ( int i = args.length - 1; i >= 0; i-- )
256 {
257 cloned[i] = (Argument) args[i].clone();
258 }
259
260 ret.setArguments( cloned );
261 return ret;
262 }
263 catch ( CloneNotSupportedException e )
264 {
265 throw new AssertionError( e );
266 }
267 }
268
269 //------------------------------------------------------------------Object--
270 }