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.layout;
021    
022    import net.dpml.transit.Artifact;
023    import net.dpml.transit.Layout;
024    import net.dpml.transit.TransitRuntimeException;
025    
026    /** 
027     * The ModernLayout decodes artifacts into a layout scheme that follows the
028     * convention of group/name/version/expanded-name pattern.  Specifically the 
029     * layout maps artifacts according to the rule
030     * [group[/[subgroup[/...]]]/[name]/[version]/name[-[version]].type.
031     * Example: <code>artifact:jar:metro/cache/dpml-cache-main#1.0.0</code>
032     * would return the path <code>metro/cache/dpml-cache-main/1.0.0/dpml-cache-main-1.0.0.jar</code>.
033     *
034     * @author <a href="http://www.dpml.net">Digital Product Management Laboratory</a>
035     * @version 2.0.1
036     */
037    public class ModernLayout
038        extends Layout
039    {
040        private static final String LAYOUT_IDENTIFIER = "modern";
041        
042        /**
043         * Return the layout identifier.  The id value is used
044         * to identify layout instances assigned to cache handlers and 
045         * resource host handlers.
046         *
047         * @return the layout id
048         */
049        public String getID()
050        {
051            return LAYOUT_IDENTIFIER;
052        }
053        
054        /**
055         * Return the base path for an artifact.  The base path is derived from
056         * the artifact group and type.  The base path value represents
057         * the directory path relative to a repository root of the directory containing
058         * this artifact.
059         *
060         * @param artifact the resource artifact
061         * @return the base path
062         */
063        public final String resolveBase( Artifact artifact )
064        {
065            String version = artifact.getVersion();
066            if( null == version )
067            {
068                if( null == artifact.getGroup() )
069                {
070                    return artifact.getName();
071                }
072                else
073                {
074                    String group = getGroupPath( artifact );
075                    return group + "/" + artifact.getName();
076                }
077            }
078            else
079            {
080                if( null == artifact.getGroup() )
081                {
082                    return artifact.getName() + "/" + version;
083                }
084                else
085                {
086                    String group = getGroupPath( artifact );
087                    return group + "/" + artifact.getName() + "/" + version;
088                }
089            }
090        }
091        
092        /**
093         * Returns the full path of the artifact relative to a logical root directory.
094         * The full path is equivalent to the base path and artifact filename using the
095         * pattern "[base]/[filename]".  Path values may be used to resolve an artifact
096         * from a remote repository or local cache relative to the repository or cache
097         * root.
098         *
099         * @param artifact the resource artifact
100         * @see #resolveBase
101         * @see #resolveFilename
102         * @return the logical artifact path
103         */
104        public final String resolvePath( Artifact artifact )
105        {
106            return resolveBase( artifact ) + "/" + resolveFilename( artifact );
107        }
108        
109        /**
110         * Return the expanded filename of the artifact. The filename is expressed
111         * as [name]-[version].[type] or in case of a null version simply [name].[type].
112         *
113         * @param artifact the resource artifact
114         * @return the artifact expanded filename
115         */
116        public String resolveFilename( Artifact artifact )
117        {
118            String scheme = artifact.getScheme();
119            String filename = resolveBaseFilename( artifact );
120            if( "artifact".equals( scheme ) )
121            {
122                return filename;
123            }
124            else if( "link".equals( scheme ) )
125            {
126                return filename + ".link";
127            }
128            else
129            {
130                final String error = 
131                  "Protocol not recognized: " + scheme;
132                throw new TransitRuntimeException( error );
133            }
134        }
135    
136        private String resolveBaseFilename( Artifact artifact )
137        {
138            String version = artifact.getVersion();
139            if( null == version )
140            {
141                return artifact.getName() + "." + artifact.getType();
142            }
143            else
144            {
145                return artifact.getName() + "-" + version + "." + artifact.getType();
146            }
147        }
148        
149       /**
150        * To be compatible with the maven-2 strategy we need to subsitute period 
151        * characters with a group separator.
152        * @param artifact the artifact from which to resolve the group path
153        * @return the group path
154        */
155        private String getGroupPath( Artifact artifact )
156        {
157            String group = artifact.getGroup();
158            return group.replace( '.', '/' );
159        }
160    }