001    /*
002     * Copyright 2005-2006 Stephen J. McConnell.
003     *
004     * Licensed  under the  Apache License,  Version 2.0  (the "License");
005     * you may not use  this file  except in  compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     *   http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed  under the  License is distributed on an "AS IS" BASIS,
012     * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
013     * implied.
014     *
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    
019    package net.dpml.metro.info;
020    
021    import java.io.Serializable;
022    
023    import net.dpml.lang.Version;
024    
025    /**
026     * This ServiceDescriptor defines the interface and service version
027     * published by a service instance.
028     *
029     * @author <a href="http://www.dpml.net">Digital Product Meta Library</a>
030     * @version 1.0.4
031     */
032    public final class ServiceDescriptor implements Serializable
033    {
034       /**
035        * Serial version identifier.
036        */
037        static final long serialVersionUID = 1L;
038    
039       /**
040        * The name of service class.
041        */
042        private final String m_classname;
043    
044       /**
045        * The version of service class.
046        */
047        private final Version m_version;
048    
049       /**
050        * Construct a service with specified type. The type argument will be
051        * parsed for a classname and version in the form [classname]#[version].
052        * If not version is present a default 1.0.0 version will be assigned.
053        *
054        * @param spec the service specification
055        * @exception NullPointerException if the spec is null
056        */
057        public ServiceDescriptor( final String spec ) throws NullPointerException
058        {
059            this( parseClassname( spec ), parseVersion( spec ) );
060        }
061    
062       /**
063        * Construct a service with specified name, version.
064        *
065        * @param classname the name of the service
066        * @param version the version of service
067        * @exception NullPointerException if the classname or version is null
068        */
069        public ServiceDescriptor( final String classname, final Version version )
070          throws NullPointerException
071        {
072            if( null == classname )
073            {
074                throw new NullPointerException( "classname" );
075            }
076            if( classname.equals( "" ) )
077            {
078                throw new NullPointerException( "classname" );
079            }
080    
081            m_classname = classname;
082    
083            if( null == version )
084            {
085                m_version = Version.parse( "1" );
086            }
087            else
088            {
089                m_version = version;
090            }
091        }
092    
093       /**
094        * Return classname of service specification.
095        *
096        * @return the classname of the service specification
097        */
098        public String getClassname()
099        {
100            return m_classname;
101        }
102    
103        /**
104         * Return the service version.
105         *
106         * @return the version of interface
107         */
108        public Version getVersion()
109        {
110            return m_version;
111        }
112    
113       /**
114        * Determine if specified service will match this service.
115        * To match a service has to have same name and must comply with version.
116        *
117        * @param other the other ServiceInfo
118        * @return true if matches, false otherwise
119        */
120        public boolean matches( final ServiceDescriptor other )
121        {
122            if( !m_classname.equals( other.m_classname ) )
123            {
124                return false;
125            }
126            else
127            {
128                return other.getVersion().complies( getVersion() );
129            }
130        }
131    
132        /**
133         * Convert to a string of format name:version
134         *
135         * @return string describing service
136         */
137        public String toString()
138        {
139            return getClassname() + ":" + getVersion();
140        }
141    
142       /**
143        * Compare this object with another for equality.
144        * @param other the object to compare this object with
145        * @return TRUE if the supplied object is a reference, service, or service
146        *   descriptor that matches this objct in terms of classname and version
147        */
148        public boolean equals( Object other )
149        {
150            if( !( other instanceof ServiceDescriptor ) )
151            {
152                return false;
153            }
154            
155            ServiceDescriptor service = (ServiceDescriptor) other;
156            if( !getClassname().equals( service.getClassname() ) )
157            {
158                return false;
159            }
160            else
161            {
162                return getVersion().equals( service.getVersion() );
163            }
164        }
165    
166       /**
167        * Returns the cashcode.
168        * @return the hascode value
169        */
170        public int hashCode()
171        {
172            return getClassname().hashCode() ^ getVersion().hashCode();
173        }
174    
175        private static final String parseClassname( final String spec )
176            throws NullPointerException
177        {
178            if( spec == null )
179            {
180                throw new NullPointerException( "spec" );
181            }
182    
183            int index = spec.indexOf( "#" );
184            if( index == -1 )
185            {
186                return spec;
187            }
188            else
189            {
190                return spec.substring( 0, index );
191            }
192        }
193    
194        private static final Version parseVersion( final String spec )
195        {
196            int index = spec.indexOf( "#" );
197            if( index == -1 )
198            {
199                return Version.parse( "1" );
200            }
201            else
202            {
203                String value = spec.substring( index + 1 );
204                return Version.parse( value );
205            }
206        }
207    }