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