001    /* 
002     * Copyright 2004 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.data;
020    
021    import java.util.Arrays;
022    
023    import net.dpml.component.Directive;
024    
025    import net.dpml.metro.info.PartReference;
026    
027    /**
028     * A context descriptor declares the context creation criteria for
029     * the context instance and context entries.
030     *
031     * <p><b>XML</b></p>
032     * <p>A context directive may contain multiple import statements.  Each import
033     * statement corresponds to a request for a context value from the container.</p>
034     * <pre>
035     *    &lt;context class="<font color="darkred">MyContextClass</font>"&gt;
036     *       &lt;entry key="<font color="darkred">special</font>"&gt;
037     *         &lt;import key="<font color="darkred">urn:avalon:classloader</font>"/&gt;
038     *       &lt;/entry&gt;
039     *       &lt;entry key="<font color="darkred">xxx</font>"&gt;
040     *         &lt;param class="<font color="darkred">MySpecialClass</font>"&gt;
041     *           &lt;param&gt<font color="darkred">hello</font>&lt;/param&gt;
042     *           &lt;param class="<font color="darkred">java.io.File</font>"&gt;<font color="darkred">../lib</font>&lt;/param&gt;
043     *         &lt;/param&gt;
044     *       &lt;/entry&gt;
045     *    &lt;/context&gt;
046     * </pre>
047     *
048     * @author <a href="http://www.dpml.net">Digital Product Meta Library</a>
049     * @version 1.2.0
050     */
051    public final class ContextDirective extends AbstractDirective implements Directive
052    {
053        //--------------------------------------------------------------------------
054        // static
055        //--------------------------------------------------------------------------
056        
057       /**
058        * Serial version identifier.
059        */
060        static final long serialVersionUID = 1L;
061        
062        private static final PartReference[] EMPTY_REFS = new PartReference[0];
063    
064        //--------------------------------------------------------------------------
065        // state
066        //--------------------------------------------------------------------------
067        
068       /**
069        * The set of entry directives.
070        */
071        private final PartReference[] m_entries;
072    
073       /**
074        * The context implementation classname.
075        */
076        private final String m_classname;
077    
078        //--------------------------------------------------------------------------
079        // constructors
080        //--------------------------------------------------------------------------
081        
082       /**
083        * Creation of a context directive.
084        */
085        public ContextDirective()
086        {
087            this( new PartReference[0] );
088        }
089    
090       /**
091        * Creation of a context directive
092        * @param entries the set of entry descriptors
093        */
094        public ContextDirective( final PartReference[] entries )
095        {
096            this( null, entries );
097        }
098    
099       /**
100        * Creation of context directive.
101        * @param classname the context implementation class
102        * @param entries the set of entry descriptors
103        */
104        public ContextDirective( final String classname, final PartReference[] entries )
105        {
106            m_classname = classname;
107            if( entries != null )
108            {
109                for( int i=0; i<entries.length; i++ )
110                {
111                    PartReference ref = entries[i];
112                    if( null == ref )
113                    {
114                        throw new NullPointerException( "entry" );
115                    }
116                }
117                m_entries = entries;
118            }
119            else
120            {
121                m_entries = EMPTY_REFS;
122            }
123        }
124    
125        //--------------------------------------------------------------------------
126        // implementation
127        //--------------------------------------------------------------------------
128        
129       /**
130        * Return the classname of the context implementation to use.
131        * @return the classname
132        */
133        public String getClassname()
134        {
135            return m_classname;
136        }
137    
138       /**
139        * Return the set of entry directives.
140        * @return the entries
141        */
142        public PartReference[] getDirectives()
143        {
144            return m_entries;
145        }
146    
147       /**
148        * Return part reference defining the value for the requested entry.
149        * @param key the context entry key
150        * @return the part reference corresponding to the supplied key or null if the
151        *   key is unknown
152        */
153        public PartReference getPartReference( String key )
154        {
155            for( int i = 0; i < m_entries.length; i++ )
156            {
157                PartReference entry = m_entries[ i ];
158                if( entry.getKey().equals( key ) )
159                {
160                    return entry;
161                }
162            }
163            return null;
164        }
165    
166       /**
167        * Return part defining the value for the requested entry.
168        * @param key the context entry key
169        * @return the part defintion corresponding to the supplied key or null if the
170        *   key is unknown
171        */
172        public Directive getPartDirective( String key )
173        {
174            PartReference ref = getPartReference( key );
175            if( null != ref )
176            {
177                return ref.getDirective();
178            }
179            else
180            {
181                return null;
182            }
183        }
184    
185       /**
186        * Test if the supplied object is equal to this object.
187        * @param other the object to compare with this instance
188        * @return TRUE if the supplied object is equal to this object
189        */
190        public boolean equals( Object other )
191        {
192            if( !super.equals( other ) )
193            {
194                return false;
195            }
196            else if( !( other instanceof ContextDirective ) )
197            {
198                return false;
199            }
200            else
201            {
202                ContextDirective context = (ContextDirective) other;
203                if( !equals( m_classname, context.m_classname ) )
204                {
205                    return false;
206                }
207                else
208                {
209                    return Arrays.equals( m_entries, context.m_entries );
210                }
211            }
212        }
213    
214       /**
215        * Return the hashcode for the instance.
216        * @return the instance hashcode
217        */
218        public int hashCode()
219        {
220            int hash = super.hashCode();
221            hash ^= hashValue( m_classname );
222            hash ^= hashArray( m_entries );
223            return hash;
224        }
225    }