EMMA Coverage Report (generated Tue Jan 14 00:37:43 CET 2014)
[all classes][org.jdtaus.core.container]

COVERAGE SUMMARY FOR SOURCE FILE [Specification.java]

nameclass, %method, %block, %line, %
Specification.java100% (1/1)47%  (14/30)56%  (262/466)46%  (42.1/92)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class Specification100% (1/1)47%  (14/30)56%  (262/466)46%  (42.1/92)
getDescription (): String 0%   (0/1)0%   (0/4)0%   (0/1)
getImplementation (String): Implementation 0%   (0/1)0%   (0/22)0%   (0/6)
getModuleName (): String 0%   (0/1)0%   (0/9)0%   (0/3)
getScope (): int 0%   (0/1)0%   (0/3)0%   (0/1)
getVendor (): String 0%   (0/1)0%   (0/9)0%   (0/3)
isSingleton (): boolean 0%   (0/1)0%   (0/8)0%   (0/1)
isStateless (): boolean 0%   (0/1)0%   (0/3)0%   (0/1)
setDescription (String): void 0%   (0/1)0%   (0/5)0%   (0/2)
setModuleName (String): void 0%   (0/1)0%   (0/4)0%   (0/2)
setMultiplicity (int): void 0%   (0/1)0%   (0/30)0%   (0/6)
setProperties (Properties): void 0%   (0/1)0%   (0/4)0%   (0/2)
setScope (int): void 0%   (0/1)0%   (0/19)0%   (0/4)
setSingleton (boolean): void 0%   (0/1)0%   (0/8)0%   (0/2)
setStateless (boolean): void 0%   (0/1)0%   (0/4)0%   (0/2)
setVendor (String): void 0%   (0/1)0%   (0/4)0%   (0/2)
setVersion (String): void 0%   (0/1)0%   (0/4)0%   (0/2)
clone (): Object 100% (1/1)33%  (3/9)33%  (1/3)
readResolve (): Object 100% (1/1)54%  (13/24)51%  (2.6/5)
setImplementations (Implementations): void 100% (1/1)61%  (36/59)67%  (7.4/11)
hashCode (): int 100% (1/1)77%  (10/13)76%  (0.8/1)
equals (Object): boolean 100% (1/1)80%  (32/40)91%  (4.5/5)
internalString (): String 100% (1/1)89%  (102/115)86%  (6.9/8)
Specification (): void 100% (1/1)100% (14/14)100% (5/5)
getIdentifier (): String 100% (1/1)100% (9/9)100% (3/3)
getImplementations (): Implementations 100% (1/1)100% (11/11)100% (3/3)
getMultiplicity (): int 100% (1/1)100% (3/3)100% (1/1)
getProperties (): Properties 100% (1/1)100% (11/11)100% (3/3)
getVersion (): String 100% (1/1)100% (3/3)100% (1/1)
setIdentifier (String): void 100% (1/1)100% (4/4)100% (2/2)
toString (): String 100% (1/1)100% (11/11)100% (1/1)

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 */
21package org.jdtaus.core.container;
22 
23import java.io.ObjectStreamException;
24import java.io.Serializable;
25import java.util.Map;
26import java.util.TreeMap;
27 
28/**
29 * Specification meta-data.
30 * <p>A specification consists of the properties {@code identifier},
31 * {@code vendor}, {@code description} and {@code version}. Property
32 * {@code identifier} holds an identifier uniquely identifying the specification
33 * in a set of specifications. Property {@code vendor} holds vendor information
34 * for the vendor providing the specification. Property {@code description}
35 * holds a textual description and property {@code version} holds a textual
36 * version of the specification. The {@code stateless} flag indicates that state
37 * does not need to be retained across operations for instances to operate as
38 * specified. Property {@code multiplicity} specifies the number of
39 * implementations allowed to exist among a set of modules. A specification with
40 * {@code MULTIPLICITY_ONE} specifies that exactly one implementation of the
41 * specification must exist among a set of modules. A specification with
42 * {@code MULTIPLICITY_MANY} specifies that multiple implementations of the
43 * specification are allowed to exist among a set of modules (including none).
44 * Property {@code scope} specifies the scope the specification applies to.
45 * In multiton scope, a new instance is created whenever requested. In context
46 * scope, instances are bound to a system's context. An instance is only created
47 * if not already available in context. In singleton scope, instances are bound
48 * to a system's single instance store. An instance is only created if not
49 * already available in that single instance store.</p>
50 *
51 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
52 * @version $JDTAUS: Specification.java 8743 2012-10-07 03:06:20Z schulte $
53 */
54public class Specification extends ModelObject
55    implements Cloneable, Serializable
56{
57    //--Constants---------------------------------------------------------------
58 
59    /**
60     * Constant for property {@code multiplicity}.
61     * <p>A specification with {@code MULTIPLICITY_ONE} specifies that exactly
62     * one implementation of the specification must exist among a set of
63     * modules.</p>
64     */
65    public static final int MULTIPLICITY_ONE = 25000;
66 
67    /**
68     * Constant for property {@code multiplicity}.
69     * <p>A specification with {@code MULTIPLICITY_MANY} specifies that multiple
70     * implementations of the specification are allowed to exist among a set of
71     * modules (including none).</p>
72     */
73    public static final int MULTIPLICITY_MANY = 25001;
74 
75    /**
76     * Constant for property {@code scope}.
77     * <p>In multiton scope, a new instance is created whenever requested.</p>
78     */
79    public static final int SCOPE_MULTITON = 26000;
80 
81    /**
82     * Constant for property {@code scope}.
83     * <p>In context scope, instances are bound to a system's context. An
84     * instance is only created if not already available in context.</p>
85     */
86    public static final int SCOPE_CONTEXT = 26001;
87 
88    /**
89     * Constant for property {@code scope}.
90     * <p>In singleton scope, instances are bound to a system's single instance
91     * store. An instance is only created if not already available in that
92     * single instance store.</p>
93     */
94    public static final int SCOPE_SINGLETON = 26002;
95 
96    /** Serial version UID for backwards compatibility with 1.0.x classes. */
97    private static final long serialVersionUID = -1829249262406961967L;
98 
99    //---------------------------------------------------------------Constants--
100    //--Specification-----------------------------------------------------------
101 
102    /**
103     * The name of the module holding the specification.
104     * @serial
105     */
106    private String moduleName;
107 
108    /**
109     * The description of the specification.
110     * @serial
111     * @deprecated Replaced by property {@code documentation}.
112     */
113    private String description;
114 
115    /**
116     * The identifier of the specification.
117     * @serial
118     */
119    private String identifier;
120 
121    /**
122     * The flag indicating that instances of implementations of the
123     * specification should be created using a singleton strategy.
124     * @serial
125     * @deprecated Replaced by {@link #scope}.
126     */
127    private boolean singleton;
128 
129    /**
130     * The vendor of the specification.
131     * @serial
132     */
133    private String vendor;
134 
135    /**
136     * The version of the specification.
137     * @serial
138     */
139    private String version;
140 
141    /**
142     * The implementation multiplicity of the specification.
143     * @serial
144     */
145    private int multiplicity = MULTIPLICITY_MANY;
146 
147    /**
148     * The scope the specification applies to.
149     * @serial
150     */
151    private int scope = SCOPE_MULTITON;
152 
153    /**
154     * The flag indicating if state need not be retained across method
155     * invocations for implementations to operate as specified.
156     * @serial
157     */
158    private boolean stateless;
159 
160    /**
161     * The implementations available for the specification.
162     * @serial
163     */
164    private Implementations implementations;
165 
166    /**
167     * Maps implementation names to implementations.
168     * @serial
169     */
170    private final Map implementationNames = new TreeMap();
171 
172    /**
173     * The properties of the specification.
174     * @serial
175     */
176    private Properties properties;
177 
178    /** Creates a new {@code Specification} instance. */
179    public Specification()
180    {
181        super();
182    }
183 
184    /**
185     * Gets the name of the module holding the specification.
186     *
187     * @return the name of the module holding the specification.
188     */
189    public String getModuleName()
190    {
191        if ( this.moduleName == null )
192        {
193            this.moduleName = "";
194        }
195 
196        return this.moduleName;
197    }
198 
199    /**
200     * Setter for property {@code moduleName}.
201     *
202     * @param value the new name of the module holding the specification.
203     */
204    public void setModuleName( final String value )
205    {
206        this.moduleName = value;
207    }
208 
209    /**
210     * Gets the description of the specification.
211     *
212     * @return the description of the specification or {@code null}.
213     *
214     * @deprecated Replaced by {@link #getDocumentation() getDocumentation().getValue()}.
215     */
216    public String getDescription()
217    {
218        return this.getDocumentation().getValue();
219    }
220 
221    /**
222     * Setter for property {@code description}.
223     *
224     * @param value the new description of the specification.
225     * @deprecated Replaced by {@link #getDocumentation() getDocumentation().setValue(value)}.
226     */
227    public void setDescription( final String value )
228    {
229        this.getDocumentation().setValue( value );
230    }
231 
232    /**
233     * Gets the identifier of the specification.
234     *
235     * @return the unique identifier of the specification.
236     */
237    public String getIdentifier()
238    {
239        if ( this.identifier == null )
240        {
241            this.identifier = "";
242        }
243 
244        return this.identifier;
245    }
246 
247    /**
248     * Setter for property {@code identifier}.
249     *
250     * @param value the new identifier of the specification.
251     */
252    public void setIdentifier( final String value )
253    {
254        this.identifier = value;
255    }
256 
257    /**
258     * Gets the flag indicating the instantiation strategy of the specification.
259     *
260     * @return {@code true} if the specification is specifying a singleton;
261     * {@code false} if not.
262     *
263     * @see PropertyOverwriteConstraintException
264     * @deprecated Replaced by {@link #getScope() getScope() == SCOPE_SINGLETON}.
265     */
266    public boolean isSingleton()
267    {
268        return this.getScope() == SCOPE_SINGLETON;
269    }
270 
271    /**
272     * Setter for property {@code singleton}.
273     *
274     * @param value {@code true} to flag the specification as a singleton;
275     * {@code false} to not flag the specification as a singleton.
276     *
277     * @see PropertyOverwriteConstraintException
278     * @deprecated Replaced by {@link #setScope(int) setScope(value ? SCOPE_SINGLETON : SCOPE_MULTITON)}.
279     */
280    public void setSingleton( final boolean value )
281    {
282        this.scope = value ? SCOPE_SINGLETON : SCOPE_MULTITON;
283    }
284 
285    /**
286     * Gets the scope the specification applies to.
287     *
288     * @return scope the specification applies to.
289     *
290     * @see #SCOPE_MULTITON
291     * @see #SCOPE_CONTEXT
292     * @see #SCOPE_SINGLETON
293     * @see PropertyOverwriteConstraintException
294     */
295    public int getScope()
296    {
297        return this.scope;
298    }
299 
300    /**
301     * Setter for property {@code scope}.
302     *
303     * @param value new scope the specification applies to.
304     *
305     * @throws IllegalArgumentException if {@code value} is not equal to one of
306     * the constants {@code SCOPE_MULTITON}, {@code SCOPE_CONTEXT} or
307     * {@code SCOPE_SINGLETON}.
308     *
309     * @see #SCOPE_MULTITON
310     * @see #SCOPE_CONTEXT
311     * @see #SCOPE_SINGLETON
312     * @see PropertyOverwriteConstraintException
313     */
314    public void setScope( final int value )
315    {
316        if ( value != SCOPE_MULTITON && value != SCOPE_CONTEXT &&
317             value != SCOPE_SINGLETON )
318        {
319            throw new IllegalArgumentException( Integer.toString( value ) );
320        }
321 
322        this.scope = value;
323    }
324 
325    /**
326     * Gets the flag indicating if state need not be retained across method
327     * invocations for implementations to operate as specified.
328     *
329     * @return {@code true} if state need not be retained across method
330     * invocations for implementations to operate as specified; {@code false} if
331     * state must be retained across method invocations for implementations
332     * to operate as specified.
333     */
334    public boolean isStateless()
335    {
336        return this.stateless;
337    }
338 
339    /**
340     * Setter for property {@code stateless}.
341     *
342     * @param value {@code true} if state need not be retained across method
343     * invocations for implementations to operate as specified; {@code false} if
344     * state must be retained across method invocations for implementations to
345     * operate as specified.
346     */
347    public void setStateless( final boolean value )
348    {
349        this.stateless = value;
350    }
351 
352    /**
353     * Gets the implementation multiplicity of the specification.
354     *
355     * @return one of the constants {@code MULTIPLICITY_ONE} or
356     * {@code MULTIPLICITY_MANY}.
357     *
358     * @see #MULTIPLICITY_ONE
359     * @see #MULTIPLICITY_MANY
360     * @see MultiplicityConstraintException
361     */
362    public int getMultiplicity()
363    {
364        return this.multiplicity;
365    }
366 
367    /**
368     * Setter for property {@code multiplicity}.
369     *
370     * @param value the new implementation multiplicity of the specification.
371     *
372     * @throws IllegalArgumentException if {@code value} is not equal to one of
373     * the constants {@code MULTIPLICITY_ONE} or {@code MULTIPLICITY_MANY}.
374     * @throws MultiplicityConstraintException if {@code value} equals
375     * {@code MULTIPLICITY_ONE} and the specification currently has more than
376     * one implementation defined.
377     *
378     * @see #MULTIPLICITY_ONE
379     * @see #MULTIPLICITY_MANY
380     */
381    public void setMultiplicity( final int value )
382    {
383        if ( value != MULTIPLICITY_ONE && value != MULTIPLICITY_MANY )
384        {
385            throw new IllegalArgumentException( Integer.toString( value ) );
386        }
387        if ( value == MULTIPLICITY_ONE && this.getImplementations().size() > 1 )
388        {
389            throw new MultiplicityConstraintException( this.getIdentifier() );
390        }
391 
392        this.multiplicity = value;
393    }
394 
395    /**
396     * Gets the vendor of the specification.
397     *
398     * @return the vendor of the specification.
399     */
400    public String getVendor()
401    {
402        if ( this.vendor == null )
403        {
404            this.vendor = "";
405        }
406 
407        return this.vendor;
408    }
409 
410    /**
411     * Setter for property {@code vendor}.
412     *
413     * @param value the new vendor of the specification.
414     */
415    public void setVendor( final String value )
416    {
417        this.vendor = value;
418    }
419 
420    /**
421     * Gets the version of the specification.
422     *
423     * @return the version of the specification or {@code null}.
424     */
425    public String getVersion()
426    {
427        return this.version;
428    }
429 
430    /**
431     * Setter for property {@code version}.
432     *
433     * @param value the new version of the specification.
434     */
435    public void setVersion( final String value )
436    {
437        this.version = value;
438    }
439 
440    /**
441     * Gets an implementation for a name.
442     *
443     * @param name the name of the implementation to return.
444     *
445     * @return a reference to the implementation named {@code name}.
446     *
447     * @throws NullPointerException if {@code name} is {@code null}.
448     * @throws MissingImplementationException if no implementation matching
449     * {@code name} exists.
450     */
451    public Implementation getImplementation( final String name )
452    {
453        if ( name == null )
454        {
455            throw new NullPointerException( "name" );
456        }
457 
458        final Implementation ret =
459            (Implementation) this.implementationNames.get( name );
460 
461        if ( ret == null )
462        {
463            throw new MissingImplementationException( name );
464        }
465 
466        return ret;
467    }
468 
469    /**
470     * Gets all available implementations of the specification.
471     *
472     * @return all available implementations of the specification.
473     */
474    public Implementations getImplementations()
475    {
476        if ( this.implementations == null )
477        {
478            this.implementations = new Implementations();
479        }
480 
481        return this.implementations;
482    }
483 
484    /**
485     * Setter for property {@code implementations}.
486     *
487     * @param value the new implementations of the specification.
488     *
489     * @throws DuplicateImplementationException if {@code value} contains
490     * duplicate implementations.
491     * @throws MultiplicityConstraintException if the specification's
492     * multiplicity equals {@code MULTIPLICITY_ONE} and {@code value} contains
493     * no or more than one implementation.
494     */
495    public void setImplementations( final Implementations value )
496    {
497        if ( this.getMultiplicity() == MULTIPLICITY_ONE && value != null &&
498             value.size() != 1 )
499        {
500            throw new MultiplicityConstraintException( this.getIdentifier() );
501        }
502 
503        this.implementationNames.clear();
504        this.implementations = null;
505 
506        if ( value != null )
507        {
508            for ( int i = value.size() - 1; i >= 0; i-- )
509            {
510                if ( this.implementationNames.put(
511                    value.getImplementation( i ).getName(),
512                    value.getImplementation( i ) ) != null )
513                {
514                    this.implementationNames.clear();
515 
516                    throw new DuplicateImplementationException(
517                        value.getImplementation( i ).getName() );
518 
519                }
520            }
521 
522            this.implementations = value;
523        }
524    }
525 
526    /**
527     * Gets the properties of the specification.
528     *
529     * @return the properties of the specification.
530     */
531    public Properties getProperties()
532    {
533        if ( this.properties == null )
534        {
535            this.properties = new Properties();
536        }
537 
538        return this.properties;
539    }
540 
541    /**
542     * Setter for property {@code properties}.
543     *
544     * @param value new properties of the specification.
545     */
546    public void setProperties( final Properties value )
547    {
548        this.properties = value;
549    }
550 
551    /**
552     * Creates a string representing the properties of the instance.
553     *
554     * @return a string representing the properties of the instance.
555     */
556    private String internalString()
557    {
558        final StringBuffer buf = new StringBuffer( 500 ).append( '{' ).
559            append( this.internalString( this ) ).
560            append( ", identifier=" ).append( this.identifier ).
561            append( ", moduleName=" ).append( this.moduleName ).
562            append( ", stateless=" ).append( this.stateless ).
563            append( ", multiplicity=" ).
564            append( this.multiplicity == MULTIPLICITY_ONE ? "one" : "many" ).
565            append( ", scope=" ).append( this.scope == SCOPE_MULTITON
566                                         ? "multiton"
567                                         : this.scope == SCOPE_CONTEXT
568                                           ? "context"
569                                           : "singleton" ).
570            append( ", vendor=" ).append( this.vendor ).
571            append( ", version=" ).append( this.version ).
572            append( ", properties=" ).append( this.getProperties() ).
573            append( ", implementations={" );
574 
575        for ( int i = this.getImplementations().size() - 1; i >= 0; i-- )
576        {
577            final Implementation impl =
578                                 this.getImplementations().getImplementation( i );
579 
580            buf.append( "[" ).append( i ).append( "]=" ).
581                append( impl.getIdentifier() ).append( "@" ).
582                append( impl.getVersion() );
583 
584            if ( i - 1 >= 0 )
585            {
586                buf.append( ", " );
587            }
588        }
589 
590        buf.append( "}}" );
591        return buf.toString();
592    }
593 
594    //-----------------------------------------------------------Specification--
595    //--Serializable------------------------------------------------------------
596 
597    /**
598     * Takes care of initializing fields when constructed from an 1.0.x object
599     * stream.
600     *
601     * @throws ObjectStreamException if no scope can be resolved.
602     */
603    private Object readResolve() throws ObjectStreamException
604    {
605        if ( this.scope == SCOPE_MULTITON && this.singleton )
606        {
607            this.scope = SCOPE_SINGLETON;
608        }
609        if ( this.getDocumentation().getValue() == null &&
610             this.description != null )
611        {
612            this.getDocumentation().setValue( this.description );
613        }
614 
615        return this;
616    }
617 
618    //------------------------------------------------------------Serializable--
619    //--Object------------------------------------------------------------------
620 
621    /**
622     * Returns a string representation of the object.
623     *
624     * @return a string representation of the object.
625     */
626    public String toString()
627    {
628        return super.toString() + this.internalString();
629    }
630 
631    /**
632     * Creates and returns a copy of this object. This method  performs a
633     * "shallow copy" of this object, not a "deep copy" operation.
634     *
635     * @return a clone of this instance.
636     */
637    public Object clone()
638    {
639        try
640        {
641            return super.clone();
642        }
643        catch ( final CloneNotSupportedException e )
644        {
645            throw new AssertionError( e );
646        }
647    }
648 
649    /**
650     * Indicates whether some other object is equal to this one by comparing
651     * properties {@code identifier} and {@code version}.
652     *
653     * @param o the reference object with which to compare.
654     *
655     * @return {@code true} if this object is the same as {@code o};
656     * {@code false} otherwise.
657     */
658    public final boolean equals( final Object o )
659    {
660        boolean equal = o == this;
661        if ( !equal && o instanceof Specification )
662        {
663            final Specification that = (Specification) o;
664            equal = this.getIdentifier().equals( that.getIdentifier() ) &&
665                    ( this.getVersion() == null ? that.getVersion() == null
666                      : this.getVersion().equals( that.getVersion() ) );
667 
668        }
669 
670        return equal;
671    }
672 
673    /**
674     * Returns a hash code value for this object.
675     *
676     * @return a hash code value for this object.
677     */
678    public final int hashCode()
679    {
680        return this.getIdentifier().hashCode() +
681               ( this.getVersion() == null ? 0 : this.getVersion().hashCode() );
682 
683    }
684 
685    //------------------------------------------------------------------Object--
686}

[all classes][org.jdtaus.core.container]
EMMA 2.1.5320 (stable) (C) Vladimir Roubtsov