001package org.apache.maven.scm.provider.integrity;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 * http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import com.mks.api.Command;
023import com.mks.api.FileOption;
024import com.mks.api.Option;
025import com.mks.api.response.APIException;
026import com.mks.api.response.Response;
027import com.mks.api.response.WorkItem;
028
029import java.io.File;
030import java.util.Date;
031
032/**
033 * This class represents an Integrity SCM Member
034 * <br>It contains all the necessary metadata to check this file out individually
035 *
036 * @author <a href="mailto:cletus@mks.com">Cletus D'Souza</a>
037 * @since 1.6
038 */
039public class Member
040{
041    private String memberID;
042
043    private String memberName;
044
045    private Date memberTimestamp;
046
047    private String memberDescription;
048
049    private String projectConfigPath;
050
051    private String memberRev;
052
053    private File targetFile;
054
055    private String relativeFile;
056
057    private String lineTerminator;
058
059    private String overwriteExisting;
060
061    private String restoreTimestamp;
062
063    /**
064     * This class represents an MKS Integrity Source File
065     * It needs the Member Name (relative path to pj), Full Member Path, Project Configuration Path, Revision,
066     * Project's Root Path, and the current Workspace directory (to compute the working file path) for its
067     * instantiation.  This helper class will be used to then perform a project checkout from the repository
068     *
069     * @param wi           A MKS API Response Work Item representing metadata related to a Integrity Member
070     * @param configPath   Configuration Path for this file's project/subproject
071     * @param projectRoot  Full path to the root location for this file's parent project
072     * @param workspaceDir Full path to the workspace root directory
073     */
074    public Member( WorkItem wi, String configPath, String projectRoot, String workspaceDir )
075    {
076        // Initialize our parent with the information needed
077        this.projectConfigPath = configPath;
078        this.memberID = wi.getId();
079        this.memberName = wi.getField( "name" ).getValueAsString();
080        this.memberRev = wi.getField( "memberrev" ).getItem().getId();
081        this.memberTimestamp = wi.getField( "membertimestamp" ).getDateTime();
082        if ( null != wi.getField( "memberdescription" ) && null != wi.getField(
083            "memberdescription" ).getValueAsString() )
084        {
085            this.memberDescription = wi.getField( "memberdescription" ).getValueAsString();
086        }
087        else
088        {
089            this.memberDescription = new String( "" );
090        }
091        this.lineTerminator = "native";
092        this.overwriteExisting = "overwriteExisting";
093        this.restoreTimestamp = "restoreTimestamp";
094        this.relativeFile = this.memberName.substring( projectRoot.length() );
095        this.targetFile = new File( workspaceDir + relativeFile );
096    }
097
098    /**
099     * Returns a string representation of this file's full path name, where it will checked out to disk for the build.
100     *
101     * @return
102     */
103    public String getTargetFilePath()
104    {
105        return targetFile.getAbsolutePath();
106    }
107
108    /**
109     * Returns a string representation of this member's revision
110     *
111     * @return
112     */
113    public String getRevision()
114    {
115        return memberRev;
116    }
117
118    /**
119     * Returns the date/time associated with this member revision
120     *
121     * @return
122     */
123    public Date getTimestamp()
124    {
125        return memberTimestamp;
126    }
127
128    /**
129     * Returns any check-in comments associated with this revision
130     *
131     * @return
132     */
133    public String getDescription()
134    {
135        return memberDescription;
136    }
137
138    /**
139     * Returns the full server-side member path for this member
140     *
141     * @return
142     */
143    public String getMemberName()
144    {
145        return memberName;
146    }
147
148    /**
149     * Returns only the file name portion for this full server-side member path
150     *
151     * @return
152     */
153    public String getName()
154    {
155        if ( memberID.indexOf( '/' ) > 0 )
156        {
157            return memberID.substring( memberID.lastIndexOf( '/' ) + 1 );
158        }
159        else if ( memberID.indexOf( '\\' ) > 0 )
160        {
161            return memberID.substring( memberID.lastIndexOf( '\\' ) + 1 );
162        }
163        else
164        {
165            return memberID;
166        }
167    }
168
169    /**
170     * Optionally, one may set a line terminator, if the default is not desired.
171     *
172     * @param lineTerminator
173     */
174    public void setLineTerminator( String lineTerminator )
175    {
176        this.lineTerminator = lineTerminator;
177    }
178
179    /**
180     * Optionally, one may choose not to overwrite existing files, this may speed up the synchronization process.
181     *
182     * @param overwriteExisting
183     */
184    public void setOverwriteExisting( String overwriteExisting )
185    {
186        this.overwriteExisting = overwriteExisting;
187    }
188
189    /**
190     * Optionally, one might want to restore the timestamp, if the build is smart not to recompile files that were not
191     * touched.
192     *
193     * @param restoreTime
194     */
195    public void setRestoreTimestamp( boolean restoreTime )
196    {
197        if ( restoreTime )
198        {
199            this.restoreTimestamp = "restoreTimestamp";
200        }
201        else
202        {
203            this.restoreTimestamp = "norestoreTimestamp";
204        }
205    }
206
207    /**
208     * Performs a checkout of this MKS Integrity Source File to a working file location on the build server represented
209     * by targetFile
210     *
211     * @param api MKS API Session
212     * @return true if the operation succeeded or false if failed
213     * @throws APIException
214     */
215    public boolean checkout( APISession api )
216        throws APIException
217    {
218        // Make sure the directory is created
219        if ( !targetFile.getParentFile().isDirectory() )
220        {
221            targetFile.getParentFile().mkdirs();
222        }
223        // Construct the project check-co command
224        Command coCMD = new Command( Command.SI, "projectco" );
225        coCMD.addOption( new Option( overwriteExisting ) );
226        coCMD.addOption( new Option( "nolock" ) );
227        coCMD.addOption( new Option( "project", projectConfigPath ) );
228        coCMD.addOption( new FileOption( "targetFile", targetFile ) );
229        coCMD.addOption( new Option( restoreTimestamp ) );
230        coCMD.addOption( new Option( "lineTerminator", lineTerminator ) );
231        coCMD.addOption( new Option( "revision", memberRev ) );
232        // Add the member selection
233        coCMD.addSelection( memberID );
234
235        // Execute the checkout command
236        Response res = api.runCommand( coCMD );
237
238        // Return true if we were successful
239        return ( res.getExitCode() == 0 );
240    }
241
242    /**
243     * Uses the name of file for equality check
244     */
245    @Override
246    public boolean equals( Object o )
247    {
248        if ( o instanceof Member )
249        {
250            return ( (Member) o ).getMemberName().equals( this.getMemberName() );
251        }
252        return false;
253    }
254
255    @Override
256    public int hashCode()
257    {
258        return this.getMemberName().hashCode();
259    }
260}