001    /*
002     * Copyright 2004-2005 Stephen J. McConnell.
003     * Copyright 2004 Niclas Hedhman.
004     *
005     * Licensed  under the  Apache License,  Version 2.0  (the "License");
006     * you may not use  this file  except in  compliance with the License.
007     * You may obtain a copy of the License at
008     *
009     *   http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed  under the  License is distributed on an "AS IS" BASIS,
013     * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
014     * implied.
015     *
016     * See the License for the specific language governing permissions and
017     * limitations under the License.
018     */
019    
020    package net.dpml.transit;
021    
022    /** 
023     * The ModernLayout decodes artifacts into a layout scheme that follows the
024     * convention of group/name/version/expanded-name pattern.  Specifically the 
025     * layout maps artifacts according to the rule
026     * [group[/[subgroup[/...]]]/[name]/[version]/name[-[version]].type.
027     * Example: <code>artifact:jar:metro/cache/dpml-cache-main#1.0.0</code>
028     * would return the path <code>metro/cache/dpml-cache-main/1.0.0/dpml-cache-main-1.0.0.jar</code>.
029     *
030     * @author <a href="http://www.dpml.net">Digital Product Meta Library</a>
031     * @version 1.0.3
032     */
033    public class ModernLayout
034        implements Layout
035    {
036        /**
037         * Return the base path for an artifact.  The base path is derived from
038         * the artifact group and type.  The base path value represents
039         * the directory path relative to a repository root of the directory containing
040         * this artifact.
041         *
042         * @param artifact the resource artifact
043         * @return the base path
044         */
045        public final String resolveBase( Artifact artifact )
046        {
047            String version = artifact.getVersion();
048            if( null == version )
049            {
050                if( null == artifact.getGroup() )
051                {
052                    return artifact.getName();
053                }
054                else
055                {
056                    String group = getGroupPath( artifact );
057                    return group + "/" + artifact.getName();
058                }
059            }
060            else
061            {
062                if( null == artifact.getGroup() )
063                {
064                    return artifact.getName() + "/" + version;
065                }
066                else
067                {
068                    String group = getGroupPath( artifact );
069                    return group + "/" + artifact.getName() + "/" + version;
070                }
071            }
072        }
073        
074        /**
075         * Returns the full path of the artifact relative to a logical root directory.
076         * The full path is equivalent to the base path and artifact filename using the
077         * pattern "[base]/[filename]".  Path values may be used to resolve an artifact
078         * from a remote repository or local cache relative to the repository or cache
079         * root.
080         *
081         * @param artifact the resource artifact
082         * @see #resolveBase
083         * @see #resolveFilename
084         * @return the logical artifact path
085         */
086        public final String resolvePath( Artifact artifact )
087        {
088            return resolveBase( artifact ) + "/" + resolveFilename( artifact );
089        }
090        
091        /**
092         * Return the expanded filename of the artifact. The filename is expressed
093         * as [name]-[version].[type] or in case of a null version simply [name].[type].
094         *
095         * @param artifact the resource artifact
096         * @return the artifact expanded filename
097         */
098        public String resolveFilename( Artifact artifact )
099        {
100            String scheme = artifact.getScheme();
101            String filename = resolveBaseFilename( artifact );
102            if( "artifact".equals( scheme ) )
103            {
104                return filename;
105            }
106            else if( "link".equals( scheme ) )
107            {
108                return filename + ".link";
109            }
110            else
111            {
112                final String error = 
113                  "Protocol not recognized: " + scheme;
114                throw new TransitRuntimeException( error );
115            }
116        }
117    
118        private String resolveBaseFilename( Artifact artifact )
119        {
120            String version = artifact.getVersion();
121            if( null == version )
122            {
123                return artifact.getName() + "." + artifact.getType();
124            }
125            else
126            {
127                return artifact.getName() + "-" + version + "." + artifact.getType();
128            }
129        }
130        
131       /**
132        * To be compatible with the maven-2 strategy we need to subsitute period 
133        * characters with a group separator.
134        * @param artifact the artifact from which to resolve the group path
135        * @return the group path
136        */
137        private String getGroupPath( Artifact artifact )
138        {
139            String group = artifact.getGroup();
140            return group.replace( '.', '/' );
141        }
142    }