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 implementations.
030 *
031 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
032 * @version $Id: Implementations.java 2230 2007-03-26 01:37:48Z schulte2005 $
033 */
034 public class Implementations implements Cloneable, Serializable
035 {
036
037 //--Implementations---------------------------------------------------------
038
039 /**
040 * The implementations held by the instance.
041 * @serial
042 */
043 private Implementation[] implementations;
044
045 /**
046 * Maps implementation identifiers to implementations.
047 * @serial
048 */
049 private final Map identifiers = new HashMap();
050
051 /**
052 * Hash code.
053 * @serial
054 */
055 private int hashCode;
056
057 /**
058 * Gets all implementations of the collection.
059 *
060 * @return all implementations of the collection.
061 */
062 public Implementation[] getImplementations()
063 {
064 if(this.implementations == null)
065 {
066 this.implementations = new Implementation[0];
067 this.hashCode = 0;
068 }
069
070 return this.implementations;
071 }
072
073 /**
074 * Setter for property {@code implementations}.
075 *
076 * @param value the new implementations for the instance.
077 *
078 * @throws DuplicateImplementationException if {@code value} contains
079 * duplicate implementations.
080 */
081 public void setImplementations(final Implementation[] value)
082 {
083 this.identifiers.clear();
084 this.hashCode = 0;
085 this.implementations = 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
093 if(this.identifiers.put(value[i].getIdentifier(),
094 value[i]) != null)
095 {
096 throw new DuplicateImplementationException(
097 value[i].getIdentifier());
098
099 }
100 }
101 }
102 }
103
104 /**
105 * Gets an implementation for an identifier.
106 *
107 * @param identifier the identifier of the implementation to return.
108 *
109 * @return a reference to the implementation identified by
110 * {@code identifier}.
111 *
112 * @throws NullPointerException if {@code identifier} is {@code null}.
113 * @throws MissingImplementationException if no implementation matching
114 * {@code identifier} exists in the collection.
115 */
116 public Implementation getImplementation(final String identifier)
117 {
118 if(identifier == null)
119 {
120 throw new NullPointerException("identifier");
121 }
122
123 final Implementation ret =
124 (Implementation) this.identifiers.get(identifier);
125
126 if(ret == null)
127 {
128 throw new MissingImplementationException(identifier);
129 }
130
131 return ret;
132 }
133
134 /**
135 * Gets an implementation for an index.
136 *
137 * @param index the index of the implementation to return.
138 *
139 * @return a reference to the implementation at {@code index}.
140 *
141 * @throws IndexOutOfBoundsException if {@code index} is negativ,
142 * greater than or equal to {@code size()}.
143 */
144 public final Implementation getImplementation(final int index)
145 {
146 if(index < 0 || index >= this.size())
147 {
148 throw new ArrayIndexOutOfBoundsException(index);
149 }
150
151 return this.getImplementations()[index];
152 }
153
154 /**
155 * Gets the number of implementations held by the instance.
156 *
157 * @return the number of implementations held by the instance.
158 */
159 public final int size()
160 {
161 return this.getImplementations().length;
162 }
163
164 /**
165 * Creates a string representing the properties of the instance.
166 *
167 * @return a string representing the properties of the instance.
168 */
169 private String internalString()
170 {
171 final StringBuffer buf = new StringBuffer(200);
172 final Implementation[] implementations = this.getImplementations();
173 for(int i = implementations.length - 1; i >= 0; i--)
174 {
175 buf.append("\n\timplementation[").append(i).append("]=").
176 append(implementations[i]);
177
178 }
179
180 return buf.toString();
181 }
182
183 //---------------------------------------------------------Implementations--
184 //--Object------------------------------------------------------------------
185
186 /**
187 * Indicates whether some other object is equal to this one by comparing
188 * the values of all properties.
189 *
190 * @param o the reference object with which to compare.
191 *
192 * @return {@code true} if this object is the same as {@code o};
193 * {@code false} otherwise.
194 */
195 public boolean equals(final Object o)
196 {
197 boolean equal = this == o;
198
199 if(!equal && o instanceof Implementations)
200 {
201 final Implementations that = (Implementations) o;
202 final Collection these = Arrays.asList(this.getImplementations());
203 final Collection those = Arrays.asList(that.getImplementations());
204
205 equal = these.size() == that.size() && these.containsAll(those);
206 }
207
208 return equal;
209 }
210
211 /**
212 * Returns a hash code value for this object.
213 *
214 * @return a hash code value for this object.
215 */
216 public int hashCode()
217 {
218 return this.hashCode;
219 }
220
221 /**
222 * Returns a string representation of the object.
223 *
224 * @return a string representation of the object.
225 */
226 public String toString()
227 {
228 return super.toString() + this.internalString();
229 }
230
231 /**
232 * Creates and returns a deep copy of this object.
233 *
234 * @return a clone of this instance.
235 */
236 public Object clone()
237 {
238 try
239 {
240 final Implementations ret = (Implementations) super.clone();
241 final Implementation[] impls = this.getImplementations();
242 ret.implementations = new Implementation[impls.length];
243
244 for(int i = impls.length - 1; i >= 0; i--)
245 {
246 ret.implementations[i] = (Implementation) impls[i].clone();
247 }
248
249 return ret;
250 }
251 catch(CloneNotSupportedException e)
252 {
253 throw new AssertionError(e);
254 }
255 }
256
257 //------------------------------------------------------------------Object--
258
259 }