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.library.info;
020    
021    import net.dpml.library.Feature;
022    import net.dpml.library.Resource;
023    import net.dpml.library.ResourceNotFoundException;
024    import net.dpml.library.Type;
025    
026    /**
027     * Simple value filter.
028     *
029     * @author <a href="http://www.dpml.net">Digital Product Meta Library</a>
030     * @version 1.2.0
031     */
032    public class FeatureFilterDirective extends FilterDirective
033    {
034        private final Feature m_feature;
035        private final boolean m_alias;
036        private String m_reference;
037        private String m_type;
038        
039       /**
040        * Creation of a new anonymous resource directive.
041        * @param token the filter token
042        * @param ref an external resource refernce (possibly null)
043        * @param feature the resource feature
044        * @param type the resource type
045        * @param alias if the alias flag
046        */
047        public FeatureFilterDirective( String token, String ref, Feature feature, String type, boolean alias )
048        {
049            super( token );
050            m_reference = ref;
051            m_feature = feature;
052            m_type = type;
053            m_alias = alias;
054        }
055        
056       /**
057        * Get the resource ref value.  
058        * If null the ref shall be interprited as the enclosing project.
059        * @return the ref value
060        */
061        public String getResourceReference()
062        {
063            return m_reference;
064        }
065        
066       /**
067        * Return the filter value.
068        * @param resource the enclosing resource
069        * @return the resolved value
070        * @exception ResourceNotFoundException if the feature references a 
071        *  resource that is unknown
072        */
073        public String getValue( Resource resource ) throws ResourceNotFoundException
074        {
075            Resource r = getReferenceResource( resource );
076            if( null == m_type )
077            {
078                return Feature.resolve( r, m_feature );
079            }
080            else
081            {
082                Type type = r.getType( m_type );
083                return Feature.resolve( r, m_feature, type, m_alias );
084            }
085            
086            /*
087            if( null != m_type && !r.isa( m_type ) )
088            {
089                final String error = 
090                  "The feature request for the type [" 
091                  + m_type 
092                  + "] from the resource ["
093                  + r 
094                  + "] cannot be fullfilled because the resource does not declare "
095                  + "production of the requested type.";
096                throw new FeatureRuntimeException( error );
097            }
098            
099            if( m_feature.equals( Feature.NAME ) )
100            {
101                return r.getName();
102            }
103            else if( m_feature.equals( Feature.GROUP ) )
104            {
105                return r.getParent().getResourcePath();
106            }
107            else if( m_feature.equals( Feature.VERSION ) )
108            {
109                String version = r.getVersion();
110                if( null == version )
111                {
112                    return "";
113                }
114                else
115                {
116                    return version;
117                }
118            }
119            else if( m_feature.equals( Feature.URI ) )
120            {
121                return resolveURIFeature( r );
122            }
123            else if( m_feature.equals( Feature.SPEC ) )
124            {
125                String path = r.getResourcePath();
126                String version = r.getVersion();
127                if( null == version )
128                {
129                    return path;
130                }
131                else
132                {
133                    return path + "#" + version;
134                }
135            }
136            else if( m_feature.equals( Feature.PATH ) )
137            {
138                if( null == m_type )
139                {
140                    final String error = 
141                      "Type attribute must be supplied in conjuction with the uri attribute.";
142                    throw new FeatureRuntimeException( error );
143                }
144                else
145                {
146                    Artifact artifact = r.getArtifact( m_type );
147                    try
148                    {
149                        File cached = 
150                          (File) artifact.toURL().getContent( new Class[]{File.class} );
151                        return cached.getCanonicalPath();
152                    }
153                    catch( Exception e )
154                    {
155                        final String error = 
156                          "Unable to resolve resource path.";
157                        throw new FeatureRuntimeException( error, e );
158                    }
159                }
160            }
161            else if( m_feature.equals( Feature.FILENAME ) )
162            {
163                if( null == m_type )
164                {
165                    final String error = 
166                      "Type attribute must be supplied in conjuction with the filename attribute.";
167                    throw new IllegalArgumentException( error );
168                }
169                return r.getLayoutPath( m_type );
170            }
171            else
172            {
173                final String error = 
174                  "Invalid feature [" + m_feature + "].";
175                throw new FeatureRuntimeException( error );
176            }
177            */
178        }
179        /*
180        private String resolveURIFeature( Resource resource )
181        {
182            if( null == m_type )
183            {
184                final String error = 
185                  "Type attribute must be supplied in conjuction with the uri attribute.";
186                throw new FeatureRuntimeException( error );
187            }
188            else
189            {
190                if( m_alias )
191                {
192                    Type type = resource.getType( m_type );
193                    Version version = type.getVersion();
194                    if( null != version )
195                    {
196                        Artifact artifact = resource.getArtifact( m_type );
197                        String group = artifact.getGroup();
198                        String name = artifact.getName();
199                        if( Version.NULL_VERSION.equals( version ) )
200                        {
201                            return "link:" 
202                              + m_type 
203                              + ":" 
204                              + group
205                              + "/" 
206                              + name; 
207                        }
208                        else
209                        {
210                            int major = version.getMajor();
211                            int minor = version.getMinor();
212                            return "link:" 
213                              + m_type 
214                              + ":" 
215                              + group 
216                              + "/" 
217                              + name
218                              + "#"
219                              + major
220                              + "."
221                              + minor;
222                        }
223                    }
224                    else
225                    {
226                        final String error = 
227                          "Cannot resolve link from resource [" 
228                          + resource
229                          + "] because the resource does not declare production of an alias for the type ["
230                          + type.getID() 
231                          + "].";
232                        throw new FeatureRuntimeException( error );
233                    }
234                }
235                else
236                {
237                    Artifact artifact = resource.getArtifact( m_type );
238                    return artifact.toURI().toASCIIString();
239                }
240            }
241        }
242        */
243        
244        private Resource getReferenceResource( Resource resource ) throws ResourceNotFoundException
245        {
246            if( null == m_reference )
247            {
248                return resource;
249            }
250            else
251            {
252                return resource.getLibrary().getResource( m_reference );
253            }
254        }
255        
256       /**
257        * Compare this object with another for equality.
258        * @param other the other object
259        * @return true if equal
260        */
261        public boolean equals( Object other )
262        {
263            if( super.equals( other ) && ( other instanceof FeatureFilterDirective ) )
264            {
265                FeatureFilterDirective directive = (FeatureFilterDirective) other;
266                if( !m_feature.equals( directive.m_feature ) )
267                {
268                    return false;
269                }
270                else if( !m_type.equals( directive.m_type ) )
271                {
272                    return false;
273                }
274                else if( !m_reference.equals( directive.m_reference ) )
275                {
276                    return false;
277                }
278                else
279                {
280                    return m_alias == directive.m_alias;
281                }
282            }
283            else
284            {
285                return false;
286            }
287        }
288        
289       /**
290        * Compute the hash value.
291        * @return the hashcode value
292        */
293        public int hashCode()
294        {
295            int hash = super.hashCode();
296            hash ^= super.hashValue( m_feature );
297            hash ^= super.hashValue( m_reference );
298            hash ^= super.hashValue( m_type );
299            if( m_alias )
300            {
301                hash ^= 1;
302            }
303            else
304            {
305                hash ^= -1;
306            }
307            return hash;
308        }
309    }