001    /*
002     * Copyright 2005 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.lang;
020    
021    import java.util.Arrays;
022    
023    /**
024     * A object resolvable from primitive arguments.
025     * 
026     * @author <a href="http://www.dpml.net">Digital Product Meta Library</a>
027     * @version 1.0.3
028     */
029    public class ValueDirective extends AbstractDirective
030    {
031        private final String m_method;
032        private final String m_target;
033        private final String m_value;
034        private final ValueDirective[] m_args;
035        private final boolean m_compound;
036    
037       /**
038        * Create a new value descriptor using the default java.lang.String class as the base type.
039        * @param value the construct value
040        */
041        public ValueDirective( String value )
042        {
043            this( null, null, value );
044        }
045    
046       /**
047        * Create a new construct using a supplied target definition.  The target argument 
048        * may be either a classname or a symbolic object reference in the form ${[key]}.
049        *
050        * @param target a classname or symbolic object reference
051        * @param value the construct value
052        */
053        public ValueDirective( String target, String value )
054        {
055            this( target, null, value );
056        }
057    
058       /**
059        * Create a new construct using a supplied target defintion.  The target argument 
060        * may be either a classname or a symbolic reference in the form ${[key]}.  If the 
061        * argument is symbolic it is resolved relative to a context map supplied by the 
062        * application resolving construct values.  If the construct value is symbolic
063        * the implementation will attempt to expand the reference relative to a context
064        * map (if supplied) otherwise the implementation will attempt to expand the value 
065        * using system properties.
066        *
067        * @param target a classname or symbolic reference
068        * @param method the method to invoke on the target
069        * @param value the construct value
070        */
071        public ValueDirective( String target, String method, String value )
072        {
073            super();
074            m_target = target;
075            m_method = method;
076            m_value = value;
077            m_args = new ValueDirective[0];
078            m_compound = false;
079        }
080    
081       /**
082        * Create a new construct using a supplied target defintion.  The target argument 
083        * may be either a classname or a symbolic reference in the form ${[key]}.  If the 
084        * argument is symbolic it is resolved relative to a context map supplied by the 
085        * application resolving construct values. Instance values resolved from the 
086        * supplied Value[] will be used as constructor arguments when resolving the target.
087        *
088        * @param target the construct classname
089        * @param args an array of unresolved parameter values
090        */
091        public ValueDirective( String target, ValueDirective[] args )
092        {
093            this( target, null, args );
094        }
095        
096       /**
097        * Create a new construct using a supplied target defintion.  The target argument 
098        * may be either a classname or a symbolic reference in the form ${[key]}.  If the 
099        * argument is symbolic it is resolved relative to a context map supplied by the 
100        * application resolving construct values. Instance values resolved from the 
101        * supplied Value[] will be used as method arguments when resolving the target.
102        *
103        * @param target the construct classname
104        * @param method the method to invoke on the target
105        * @param args an array of unresolved parameter values
106        */
107        public ValueDirective( String target, String method, ValueDirective[] args )
108        {
109            super();
110            if( null == args )
111            {
112                m_args = new ValueDirective[0];
113            }
114            else
115            {
116                m_args = args;
117            }
118            m_value = null;
119            m_target = target;
120            m_method = method;
121            m_compound = true;
122        }
123        
124       /**
125        * Return TRUE if this construct is a compund construct else FALSE.
126        * @return TRUE if this ia a compound construct
127        */
128        public boolean isCompound()
129        {
130            return m_compound;
131        }
132    
133       /**
134        * Return the method name to be applied to the target object.
135        * @return the method name
136        */
137        public String getMethodName()
138        {
139            return m_method;
140        }
141    
142       /**
143        * Return the set of nested values within this value.
144        * @return the nested values array
145        */
146        public ValueDirective[] getValueDirectives()
147        {
148            return m_args;
149        }
150    
151       /**
152        * Return the base value of the resolved value.
153        * @return the base value
154        */
155        public String getBaseValue()
156        {
157            return m_value;
158        }
159    
160       /**
161        * Return the classname of the resolved value.
162        * @return the classname
163        */
164        public String getTargetExpression()
165        {
166            return m_target;
167        }
168    
169       /**
170        * Return a string representation of the construct.
171        * @return the string value
172        */
173        public String toString()
174        {
175            if( !m_compound )
176            {
177                return "value "
178                  + " target: " + m_target 
179                  + " method: " + m_method 
180                  + " value: " + m_value;
181            }
182            else
183            {
184                return "value "
185                  + " target: " + m_target 
186                  + " method: " + m_method 
187                  + " values: " + m_args.length;
188            }
189        }
190        
191       /**
192        * Compare this instance with a supplied object for equality.
193        * @param other the other object
194        * @return true if the supplied instance is equal to this instance
195        */
196        public boolean equals( Object other )
197        {
198            if( super.equals( other ) && ( other instanceof ValueDirective ) )
199            {
200                ValueDirective construct = (ValueDirective) other;
201                if( !equals( m_target, construct.m_target ) )
202                {
203                    return false;
204                }
205                if( m_compound != construct.m_compound )
206                {
207                    return false;
208                }
209                if( !equals( m_method, construct.m_method ) )
210                {
211                    return false;
212                }
213                if( m_compound )
214                {
215                    return Arrays.equals( m_args, construct.m_args );
216                }
217                else
218                {
219                    return equals( m_value, construct.m_value );
220                }
221            }
222            else
223            {
224                return false;
225            }
226        }
227        
228       /**
229        * Compute the instance hashcode value.
230        * @return the hashcode
231        */
232        public int hashCode()
233        {
234            int hash = 0;
235            hash ^= hashValue( m_target );
236            hash ^= hashValue( m_method );
237            hash ^= hashArray( m_args );
238            hash ^= hashValue( m_value );
239            return hash;
240        }
241    }