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 * @version $Id: Member.java 1.2 2011/08/22 13:06:47EDT Cletus D'Souza (dsouza) Exp  $
038 * @since 1.6
039 */
040public class Member
041{
042    private String memberID;
043
044    private String memberName;
045
046    private Date memberTimestamp;
047
048    private String memberDescription;
049
050    private String projectConfigPath;
051
052    private String memberRev;
053
054    private File targetFile;
055
056    private String relativeFile;
057
058    private String lineTerminator;
059
060    private String overwriteExisting;
061
062    private String restoreTimestamp;
063
064    /**
065     * This class represents an MKS Integrity Source File
066     * It needs the Member Name (relative path to pj), Full Member Path, Project Configuration Path, Revision,
067     * Project's Root Path, and the current Workspace directory (to compute the working file path) for its
068     * instantiation.  This helper class will be used to then perform a project checkout from the repository
069     *
070     * @param wi           A MKS API Response Work Item representing metadata related to a Integrity Member
071     * @param configPath   Configuration Path for this file's project/subproject
072     * @param projectRoot  Full path to the root location for this file's parent project
073     * @param workspaceDir Full path to the workspace root directory
074     */
075    public Member( WorkItem wi, String configPath, String projectRoot, String workspaceDir )
076    {
077        // Initialize our parent with the information needed
078        this.projectConfigPath = configPath;
079        this.memberID = wi.getId();
080        this.memberName = wi.getField( "name" ).getValueAsString();
081        this.memberRev = wi.getField( "memberrev" ).getItem().getId();
082        this.memberTimestamp = wi.getField( "membertimestamp" ).getDateTime();
083        if ( null != wi.getField( "memberdescription" ) && null != wi.getField(
084            "memberdescription" ).getValueAsString() )
085        {
086            this.memberDescription = wi.getField( "memberdescription" ).getValueAsString();
087        }
088        else
089        {
090            this.memberDescription = new String( "" );
091        }
092        this.lineTerminator = "native";
093        this.overwriteExisting = "overwriteExisting";
094        this.restoreTimestamp = "restoreTimestamp";
095        this.relativeFile = this.memberName.substring( projectRoot.length() );
096        this.targetFile = new File( workspaceDir + relativeFile );
097    }
098
099    /**
100     * Returns a string representation of this file's full path name, where it will checked out to disk for the build.
101     *
102     * @return
103     */
104    public String getTargetFilePath()
105    {
106        return targetFile.getAbsolutePath();
107    }
108
109    /**
110     * Returns a string representation of this member's revision
111     *
112     * @return
113     */
114    public String getRevision()
115    {
116        return memberRev;
117    }
118
119    /**
120     * Returns the date/time associated with this member revision
121     *
122     * @return
123     */
124    public Date getTimestamp()
125    {
126        return memberTimestamp;
127    }
128
129    /**
130     * Returns any check-in comments associated with this revision
131     *
132     * @return
133     */
134    public String getDescription()
135    {
136        return memberDescription;
137    }
138
139    /**
140     * Returns the full server-side member path for this member
141     *
142     * @return
143     */
144    public String getMemberName()
145    {
146        return memberName;
147    }
148
149    /**
150     * Returns only the file name portion for this full server-side member path
151     *
152     * @return
153     */
154    public String getName()
155    {
156        if ( memberID.indexOf( '/' ) > 0 )
157        {
158            return memberID.substring( memberID.lastIndexOf( '/' ) + 1 );
159        }
160        else if ( memberID.indexOf( '\\' ) > 0 )
161        {
162            return memberID.substring( memberID.lastIndexOf( '\\' ) + 1 );
163        }
164        else
165        {
166            return memberID;
167        }
168    }
169
170    /**
171     * Optionally, one may set a line terminator, if the default is not desired.
172     *
173     * @param lineTerminator
174     */
175    public void setLineTerminator( String lineTerminator )
176    {
177        this.lineTerminator = lineTerminator;
178    }
179
180    /**
181     * Optionally, one may choose not to overwrite existing files, this may speed up the synchronization process.
182     *
183     * @param overwriteExisting
184     */
185    public void setOverwriteExisting( String overwriteExisting )
186    {
187        this.overwriteExisting = overwriteExisting;
188    }
189
190    /**
191     * Optionally, one might want to restore the timestamp, if the build is smart not to recompile files that were not
192     * touched.
193     *
194     * @param restoreTimestamp
195     */
196    public void setRestoreTimestamp( boolean restoreTime )
197    {
198        if ( restoreTime )
199        {
200            this.restoreTimestamp = "restoreTimestamp";
201        }
202        else
203        {
204            this.restoreTimestamp = "norestoreTimestamp";
205        }
206    }
207
208    /**
209     * Performs a checkout of this MKS Integrity Source File to a working file location on the build server represented
210     * by targetFile
211     *
212     * @param api MKS API Session
213     * @return true if the operation succeeded or false if failed
214     * @throws APIException
215     */
216    public boolean checkout( APISession api )
217        throws APIException
218    {
219        // Make sure the directory is created
220        if ( !targetFile.getParentFile().isDirectory() )
221        {
222            targetFile.getParentFile().mkdirs();
223        }
224        // Construct the project check-co command
225        Command coCMD = new Command( Command.SI, "projectco" );
226        coCMD.addOption( new Option( overwriteExisting ) );
227        coCMD.addOption( new Option( "nolock" ) );
228        coCMD.addOption( new Option( "project", projectConfigPath ) );
229        coCMD.addOption( new FileOption( "targetFile", targetFile ) );
230        coCMD.addOption( new Option( restoreTimestamp ) );
231        coCMD.addOption( new Option( "lineTerminator", lineTerminator ) );
232        coCMD.addOption( new Option( "revision", memberRev ) );
233        // Add the member selection
234        coCMD.addSelection( memberID );
235
236        // Execute the checkout command
237        Response res = api.runCommand( coCMD );
238
239        // Return true if we were successful
240        return ( res.getExitCode() == 0 );
241    }
242
243    /**
244     * Uses the name of file for equality check
245     */
246    @Override
247    public boolean equals( Object o )
248    {
249        if ( o instanceof Member )
250        {
251            if ( null != o )
252            {
253                return ( (Member) o ).getMemberName().equals( this.getMemberName() );
254            }
255        }
256        return false;
257    }
258
259    @Override
260    public int hashCode()
261    {
262        return this.getMemberName().hashCode();
263    }
264}