View Javadoc

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 implementations.
31   *
32   * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
33   * @version $JDTAUS: Implementations.java 8743 2012-10-07 03:06:20Z schulte $
34   */
35  public class Implementations extends ModelObject
36      implements Cloneable, Serializable
37  {
38      //--Constants---------------------------------------------------------------
39  
40      /** Serial version UID for backwards compatibility with 1.0.x classes. */
41      private static final long serialVersionUID = 5611937453792676565L;
42  
43      //---------------------------------------------------------------Constants--
44      //--Implementations---------------------------------------------------------
45  
46      /**
47       * The implementations held by the instance.
48       * @serial
49       */
50      private Implementation[] implementations;
51  
52      /**
53       * Maps implementation identifiers to implementations.
54       * @serial
55       */
56      private final Map identifiers = new HashMap();
57  
58      /**
59       * Hash code.
60       * @serial
61       */
62      private int hashCode;
63  
64      /** Creates a new {@code Implementations} instance. */
65      public Implementations()
66      {
67          super();
68      }
69  
70      /**
71       * Gets all implementations of the collection.
72       *
73       * @return all implementations of the collection.
74       */
75      public Implementation[] getImplementations()
76      {
77          if ( this.implementations == null )
78          {
79              this.implementations = new Implementation[ 0 ];
80              this.hashCode = 0;
81          }
82  
83          return this.implementations;
84      }
85  
86      /**
87       * Setter for property {@code implementations}.
88       *
89       * @param value the new implementations for the instance.
90       *
91       * @throws DuplicateImplementationException if {@code value} contains
92       * duplicate implementations.
93       */
94      public void setImplementations( final Implementation[] value )
95      {
96          this.identifiers.clear();
97          this.hashCode = 0;
98          this.implementations = null;
99  
100         if ( value != null )
101         {
102             for ( int i = value.length - 1; i >= 0; i-- )
103             {
104                 this.hashCode += value[i].hashCode();
105 
106                 if ( this.identifiers.put( value[i].getIdentifier(),
107                                            value[i] ) != null )
108                 {
109                     this.identifiers.clear();
110                     this.hashCode = 0;
111 
112                     throw new DuplicateImplementationException(
113                         value[i].getIdentifier() );
114 
115                 }
116             }
117 
118             this.implementations = value;
119         }
120     }
121 
122     /**
123      * Gets an implementation for an identifier.
124      *
125      * @param identifier the identifier of the implementation to return.
126      *
127      * @return a reference to the implementation identified by
128      * {@code identifier}.
129      *
130      * @throws NullPointerException if {@code identifier} is {@code null}.
131      * @throws MissingImplementationException if no implementation matching
132      * {@code identifier} exists in the collection.
133      */
134     public Implementation getImplementation( final String identifier )
135     {
136         if ( identifier == null )
137         {
138             throw new NullPointerException( "identifier" );
139         }
140 
141         final Implementation ret =
142             (Implementation) this.identifiers.get( identifier );
143 
144         if ( ret == null )
145         {
146             throw new MissingImplementationException( identifier );
147         }
148 
149         return ret;
150     }
151 
152     /**
153      * Gets an implementation for an index.
154      *
155      * @param index the index of the implementation to return.
156      *
157      * @return a reference to the implementation at {@code index}.
158      *
159      * @throws IndexOutOfBoundsException if {@code index} is negativ,
160      * greater than or equal to {@code size()}.
161      */
162     public final Implementation getImplementation( final int index )
163     {
164         if ( index < 0 || index >= this.size() )
165         {
166             throw new ArrayIndexOutOfBoundsException( index );
167         }
168 
169         return this.getImplementations()[index];
170     }
171 
172     /**
173      * Gets the number of implementations held by the instance.
174      *
175      * @return the number of implementations held by the instance.
176      */
177     public final int size()
178     {
179         return this.getImplementations().length;
180     }
181 
182     /**
183      * Creates a string representing the properties of the instance.
184      *
185      * @return a string representing the properties of the instance.
186      */
187     private String internalString()
188     {
189         final StringBuffer buf = new StringBuffer( 200 ).append( '{' );
190         buf.append( this.internalString( this ) );
191 
192         final Implementation[] impls = this.getImplementations();
193         for ( int i = impls.length - 1; i >= 0; i-- )
194         {
195             buf.append( ", [" ).append( i ).append( "]=" ).
196                 append( impls[i] );
197 
198         }
199 
200         buf.append( '}' );
201         return buf.toString();
202     }
203 
204     //---------------------------------------------------------Implementations--
205     //--Object------------------------------------------------------------------
206 
207     /**
208      * Indicates whether some other object is equal to this one by comparing
209      * the values of all properties.
210      *
211      * @param o the reference object with which to compare.
212      *
213      * @return {@code true} if this object is the same as {@code o};
214      * {@code false} otherwise.
215      */
216     public boolean equals( final Object o )
217     {
218         boolean equal = this == o;
219 
220         if ( !equal && o instanceof Implementations )
221         {
222             final Implementations that = (Implementations) o;
223             final Collection these = Arrays.asList( this.getImplementations() );
224             final Collection those = Arrays.asList( that.getImplementations() );
225 
226             equal = this.size() == that.size() && these.containsAll( those );
227         }
228 
229         return equal;
230     }
231 
232     /**
233      * Returns a hash code value for this object.
234      *
235      * @return a hash code value for this object.
236      */
237     public int hashCode()
238     {
239         return this.hashCode;
240     }
241 
242     /**
243      * Returns a string representation of the object.
244      *
245      * @return a string representation of the object.
246      */
247     public String toString()
248     {
249         return super.toString() + this.internalString();
250     }
251 
252     /**
253      * Creates and returns a deep copy of this object.
254      *
255      * @return a clone of this instance.
256      */
257     public Object clone()
258     {
259         try
260         {
261             final Implementations ret = (Implementations) super.clone();
262             final Implementation[] impls = this.getImplementations();
263             final Implementation[] cloned = new Implementation[ impls.length ];
264 
265             for ( int i = impls.length - 1; i >= 0; i-- )
266             {
267                 cloned[i] = (Implementation) impls[i].clone();
268             }
269 
270             ret.setImplementations( cloned );
271             return ret;
272         }
273         catch ( final CloneNotSupportedException e )
274         {
275             throw new AssertionError( e );
276         }
277     }
278 
279     //------------------------------------------------------------------Object--
280 }