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.HashMap;
024 import java.util.Map;
025
026 /**
027 * Specification meta-data.
028 * <p>A specification consists of the properties {@code identifier},
029 * {@code vendor}, {@code description} and {@code version}. Property
030 * {@code identifier} holds an identifier uniquely identifying the specification
031 * in a collection of specifications. Property {@code vendor} holds vendor
032 * information for the vendor providing the specification. Property
033 * {@code description} holds a textual description and property {@code version}
034 * holds a textual version of the specification. The {@code singleton} flag
035 * indicates whether implementations of the specification should be instantiated
036 * once or whenever requested through the container.</p>
037 *
038 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
039 * @version $Id: Specification.java 2230 2007-03-26 01:37:48Z schulte2005 $
040 */
041 public class Specification implements Cloneable, Serializable
042 {
043
044 //--Specification-----------------------------------------------------------
045
046 /**
047 * The name of the module holding the specification.
048 * @serial
049 */
050 private String moduleName;
051
052 /**
053 * The description of the specification.
054 * @serial
055 */
056 private String description;
057
058 /**
059 * The identifier of the specification.
060 * @serial
061 */
062 private String identifier;
063
064 /**
065 * The flag indicating that instance of the specification should be
066 * created using a singleton strategy.
067 * @serial
068 */
069 private boolean singleton;
070
071 /**
072 * The vendor of the specification.
073 * @serial
074 */
075 private String vendor;
076
077 /**
078 * The version of the specification.
079 * @serial
080 */
081 private String version;
082
083 /**
084 * The implementations available for the specification.
085 * @serial
086 */
087 private Implementations implementations;
088
089 /**
090 * Maps implementation names to implementations.
091 * @serial
092 */
093 private final Map implementationNames = new HashMap();
094
095 /**
096 * Gets the name of the module holding the specification.
097 *
098 * @return the name of the module holding the specification.
099 */
100 public String getModuleName()
101 {
102 if(this.moduleName == null)
103 {
104 this.moduleName = "";
105 }
106
107 return this.moduleName;
108 }
109
110 /**
111 * Setter for property {@code moduleName}.
112 *
113 * @param value the new name of the module holding the specification.
114 */
115 public void setModuleName(final String value)
116 {
117 this.moduleName = value;
118 }
119
120 /**
121 * Gets the description of the specification.
122 *
123 * @return the description of the specification.
124 */
125 public String getDescription()
126 {
127 if(this.description == null)
128 {
129 this.description = "";
130 }
131
132 return this.description;
133 }
134
135 /**
136 * Setter for property {@code description}.
137 *
138 * @param value the new description of the specification.
139 */
140 public void setDescription(final String value)
141 {
142 this.description = value;
143 }
144
145 /**
146 * Gets the identifier of the specification.
147 *
148 * @return the unique identifier of the specification.
149 */
150 public String getIdentifier()
151 {
152 if(this.identifier == null)
153 {
154 this.identifier = "";
155 }
156
157 return this.identifier;
158 }
159
160 /**
161 * Setter for property {@code identifier}.
162 *
163 * @param value the new identifier of the specification.
164 */
165 public void setIdentifier(final String value)
166 {
167 this.identifier = value;
168 }
169
170 /**
171 * Gets the flag indicating the instantiation strategy of the specification.
172 *
173 * @return {@code true} if the specification is specifying a singleton;
174 * {@code false} if not.
175 */
176 public boolean isSingleton()
177 {
178 return this.singleton;
179 }
180
181 /**
182 * Setter for property {@code singleton}.
183 *
184 * @param value {@code true} to flag the specification as a singleton;
185 * {@code false} to not flag the specification as a singleton.
186 */
187 public void setSingleton(boolean value)
188 {
189 this.singleton = value;
190 }
191
192 /**
193 * Gets the vendor of the specification.
194 *
195 * @return the vendor of the specification.
196 */
197 public String getVendor()
198 {
199 if(this.vendor == null)
200 {
201 this.vendor = "";
202 }
203
204 return this.vendor;
205 }
206
207 /**
208 * Setter for property {@code vendor}.
209 *
210 * @param value the new vendor of the specification.
211 */
212 public void setVendor(final String value)
213 {
214 this.vendor = value;
215 }
216
217 /**
218 * Gets the version of the specification.
219 *
220 * @return the version of the specification.
221 */
222 public String getVersion()
223 {
224 if(this.version == null)
225 {
226 this.version = "";
227 }
228
229 return this.version;
230 }
231
232 /**
233 * Setter for property {@code version}.
234 *
235 * @param value the new version of the specification.
236 */
237 public void setVersion(final String value)
238 {
239 this.version = value;
240 }
241
242 /**
243 * Gets an implementation for a name.
244 *
245 * @param name the name of the implementation to return.
246 *
247 * @return a reference to the implementation named {@code name}.
248 *
249 * @throws NullPointerException if {@code name} is {@code null}.
250 * @throws MissingImplementationException if no implementation matching
251 * {@code name} exists.
252 */
253 public Implementation getImplementation(final String name)
254 {
255 if(name == null)
256 {
257 throw new NullPointerException("name");
258 }
259
260 final Implementation ret =
261 (Implementation) this.implementationNames.get(name);
262
263 if(ret == null)
264 {
265 throw new MissingImplementationException(name);
266 }
267
268 return ret;
269 }
270
271 /**
272 * Gets all available implementations of the specification.
273 *
274 * @return all available implementations of the specification.
275 */
276 public Implementations getImplementations()
277 {
278 if(this.implementations == null)
279 {
280 this.implementations = new Implementations();
281 }
282
283 return this.implementations;
284 }
285
286 /**
287 * Setter for property {@code implementations}.
288 *
289 * @param value the new implementations of the specification.
290 *
291 * @throws DuplicateImplementationException if {@code value} contains
292 * duplicate implementations.
293 */
294 public void setImplementations(final Implementations value)
295 {
296 if(value != null)
297 {
298 this.implementationNames.clear();
299 for(int i = value.size() - 1; i >= 0; i--)
300 {
301 if(this.implementationNames.put(
302 value.getImplementation(i).getName(),
303 value.getImplementation(i)) != null)
304 {
305
306 throw new DuplicateImplementationException(
307 value.getImplementation(i).getName());
308
309 }
310 }
311 }
312 this.implementations = value;
313 }
314
315 /**
316 * Creates a string representing the properties of the instance.
317 *
318 * @return a string representing the properties of the instance.
319 */
320 private String internalString()
321 {
322 return new StringBuffer(500).
323 append("\n\tdescription=").append(this.description).
324 append("\n\tidentifier=").append(this.identifier).
325 append("\n\timplementations=").append(this.implementations).
326 append("\n\tmoduleName=").append(this.moduleName).
327 append("\n\tsingleton=").append(this.singleton).
328 append("\n\tvendor=").append(this.vendor).
329 append("\n\tversion=").append(this.version).
330 toString();
331
332 }
333
334 //-----------------------------------------------------------Specification--
335 //--Object------------------------------------------------------------------
336
337 /**
338 * Returns a string representation of the object.
339 *
340 * @return a string representation of the object.
341 */
342 public String toString()
343 {
344 return super.toString() + this.internalString();
345 }
346
347 /**
348 * Creates and returns a deep copy of this object.
349 *
350 * @return a clone of this instance.
351 */
352 public Object clone()
353 {
354 try
355 {
356 final Specification ret = (Specification) super.clone();
357 ret.setImplementations(
358 (Implementations) this.getImplementations().clone());
359
360 return ret;
361 }
362 catch(CloneNotSupportedException e)
363 {
364 throw new AssertionError(e);
365 }
366 }
367
368 /**
369 * Indicates whether some other object is equal to this one by comparing
370 * property {@code identifier}.
371 *
372 * @param o the reference object with which to compare.
373 *
374 * @return {@code true} if this object is the same as {@code o};
375 * {@code false} otherwise.
376 */
377 public final boolean equals(final Object o)
378 {
379 return o == this || (o != null && o instanceof Specification &&
380 ((Specification)o).getIdentifier().equals(this.getIdentifier()));
381
382 }
383
384 /**
385 * Returns a hash code value for this object.
386 *
387 * @return a hash code value for this object.
388 */
389 public final int hashCode()
390 {
391 return this.getIdentifier().hashCode();
392 }
393
394 //------------------------------------------------------------------Object--
395
396 }