package com.jbase.jbuilder5vcs;
// jBuilder import
import com.borland.jbuilder.node.JBProject;
import com.borland.primetime.node.Project;
import com.borland.primetime.vfs.Url;
import com.borland.primetime.teamdev.vcs.VCSFileInfo;
import com.borland.primetime.ide.Browser;
// java import
import java.util.Set;
import java.util.List;
import java.util.Map;
import java.util.HashSet;
import java.util.ArrayList;
import java.util.HashMap;
import java.io.File;
import java.util.StringTokenizer;
/**
* Title: JBuilder/Perforce<br>
* Description: Integration of Perforce on jBuilder<br>
* This class is a mirror of the P4 client, it maintain the list of<br>
* file on the pending list and on the depot list.
* Copyright: Copyright (c) 2001<br>
* <DL><DT><b>Company:</b></DT><DD>jBase.</DD></DL>
* @author <a href="mailto:hervea@jbase.com">Herv Aubert</a>
* @author <a href="mailto:nicolasj@jbase.com">Nicolas Jorand</a>
* @version 1.0
* @since JDK 1.3
*/
public class P4ClientSpec {
public static final String KEY_CLIENT = "Client";
public static final String KEY_UPDATE = "Update";
public static final String KEY_ACCESS = "Access";
public static final String KEY_OWNER = "Owner";
public static final String KEY_HOST = "Host";
public static final String KEY_DESCRIPTION = "Description";
public static final String KEY_ROOT = "Root";
public static final String KEY_OPTIONS = "Options";
public static final String KEY_VIEW = "View";
public static final String KEY_FILES = "Files";
private String depot; //Name of the Depot
private String client; //Name of the Client
private String update; //Date of the last update
private String access; //Date of the last access
private String owner; //Name of the Owner
private String host; //Name of the Host
private String description; //Name of the Description
private String root; //The root directory on the host client
private String [] options; //The table of the different option for the sync
private String [] view; //The table of the different directory to sync
private Set _FileOnP4 = new HashSet(); // Collection with file on P4
private Set _FileOnPending = new HashSet(); // Collection with file on P4
private Map _FileStatus = (Map)new HashMap(); // File status on the project
public Url _url = null;
public P4ClientSpec() {
}
/**********************************************
* Creates new P4ClientSpec
*/
public P4ClientSpec(String ClientSpec, String sListOfFile, String sListPending) {
initClass(ClientSpec, sListOfFile, sListPending);
}
/**********************************************
* Properties Get and Set
*/
public void setDepot(String depot){
this.depot=depot;
}
public String getDepot(){
String sDepot = this.depot; // A view content the depot
try{
// The depot name are between a "//" and the next "/"
int nPosStart = sDepot.indexOf("//");
int nPosEnd = sDepot.indexOf("/",nPosStart+2); // +2 -> forget the "//" found !
if (nPosStart != -1){
sDepot = sDepot.substring(nPosStart,nPosEnd+1); // +1 -> to get the file separator
}else{
sDepot = null;
}
}catch(Exception e){
sDepot = null;
}finally{
return sDepot;
}
}
public void setClient(String client){
this.client=client;
}
public String getClient (){
return this.client;
}
public void setUpdate(String update){
this.client=client;
}
public String getUpdate (){
return this.update;
}
public void setAccess(String access){
this.access=access;
}
public String getAccess (){
return this.access;
}
public void setOwner(String owner){
this.owner=owner;
}
public String getOwner (){
return this.owner;
}
public void setHost(String host){
this.host=host;
}
public String getHost (){
return this.host;
}
public void setDescriptiont(String description){
this.description=description;
}
public String getDescription (){
return this.description;
}
public void setRoot(String root){
this.root=root;
}
public String getRoot (){
String sRoot = this.root.replace('\\','/');// P4 not support the backslash!!
return sRoot;
}
public String getOptions (int id){
return this.options[id];
}
public void setOptions(String options,int id){
this.options[id]=options;
}
/**
* Check on the collection respective (depot or pending) if <p>
* the file past on parameter exist.
*/
public boolean isUnderVCS(String sFile, int nDepotPending){
boolean bRet = false;
String sRoot = this.getRoot();
String sDepot = this.getDepot();
String sFileOnPending = "";
if (nDepotPending == Actions.ON_PENDING_LIST){
// Replace the root by the depot name
sFileOnPending = sDepot + sFile.substring(sRoot.length()+1).replace('\\','/');
}
if (nDepotPending == Actions.ON_PENDING_LIST){
if (_FileOnPending != null){
bRet = _FileOnPending.contains(sFileOnPending);
}
}else if(nDepotPending == Actions.ON_DEPOT_LIST){
if (_FileOnP4 != null){
bRet = _FileOnP4.contains(sFile.toLowerCase().replace('\\','/'));
}
}else if(nDepotPending == Actions.ON_DEP_OR_PEN_LIST){
if (_FileOnP4 != null){
bRet = _FileOnP4.contains(sFile.toLowerCase().replace('\\','/'));
}
if (!bRet & _FileOnPending != null){
bRet = _FileOnPending.contains(sFileOnPending);
}
}
return bRet;
}
/**
* Get the status list of the specified project,
*/
public Map getStatus(Project project){
_FileStatus = (Map)new HashMap();
try{
JBProject jproject = (JBProject)project;
Url[] sourcePath = jproject.getPaths().getSourcePath();
Url projectPath = jproject.getProjectPath();
Url[] totalPath = new Url[sourcePath.length+1];
System.arraycopy(sourcePath,0,totalPath,0,sourcePath.length);
// add the project path
totalPath[totalPath.length-1] = projectPath;
for (int i=0;i<totalPath.length;i++){
// For debug if jBuilder is launch on verbose mode
System.out.println("*********** P4ClientSpec:getStatus:PathOnProject["+i+"] = "+totalPath[i].getFile()+" ***********");
this.setFileStatus(totalPath[i].getFileObject());
}
System.out.println("**********************");
}catch(Exception e){
e.printStackTrace();
}finally{
System.out.println("****** RESUME ********");
System.out.println("size of FileStatus = "+_FileStatus.size());
java.util.Iterator it1 = _FileStatus.keySet().iterator();
java.util.Collection col = _FileStatus.values();
java.util.Iterator it = col.iterator();
for (int i=0;it.hasNext();i++ ) {
System.out.println("elements["+it1.next().toString()+" = ");
List l =(List)it.next();
java.util.Iterator itl = l.iterator() ;
for (;itl.hasNext(); ) {
System.out.println("\t"+itl.next().toString());
}
System.out.println("\n");
}
System.out.println("****** RESUME ********");
return (Map)_FileStatus;
}
}
/**
* Scan the first dir and all children to determine if each file is on P4 or not.<p>
* And add the file on the HashMap _FileStatus. the convention is :<p>
* (Key,Object) where:<p>
* Key = instance of FileInfo, identifies a directory.<p>
* Object = List -> ArrayList, each elements are instance of FileInfo and identifies a file.<p>
* I tried to create a tree with multiple level, but it doesn't work !!!!<p>
* I tried this:<p>
* (Key,Object) where:<p>
* Key = instance of FileInfo, identifies a directory(usually 'com').<p>
* Object = A HashMap with the subdirectory and this HashMap had a List ......
*
*/
private void setFileStatus( File startDir ) {
VCSFileInfo currentDir = null;
List currentList = null;
try {
JBProject prj = (JBProject)Browser.getActiveBrowser().getActiveProject();
Url bakPath = prj.getPaths().getBakPath();
Url outPath = prj.getPaths().getOutPath();
File[] list = startDir.listFiles();
Url url = null; // Url used to the map object
int len = list.length;
for ( int i=0; i<len; i++ ) { // For each file or directory ...
// For debug if jBuilder is launch on verbose mode
System.out.print("P4ClientSpec:setFileStatus:File["+i+"] = "+list[i]);
if (list[i].isDirectory()) {
// Is a directory, recursive call
// For debug if jBuilder is launch on verbose mode
System.out.print(" Is a directory\n");
setFileStatus(list[i]);
url = new Url(list[i]);
}else{
String fname = list[i].getCanonicalPath();
url = new Url(list[i]).getParent();
// For debug if jBuilder is launch on verbose mode
System.out.print(" Is a file and parent = "+url.getFile()+"\n");
Url urltmp = new Url(list[i]);
currentDir = new VCSFileInfo(url,new RevisionStatus(RevisionStatus.STATUS_ON_DEPOT));
currentList = (List)_FileStatus.get(currentDir);
if ( currentList == null){
currentList =(List)new ArrayList();
_FileStatus.put(currentDir, currentList);
}
// Test if is it on the project view
boolean bOnProject = true;// this doesn't work :Browser.getActiveBrowser().getActiveProject().isProjectUrl(url);
// Skip files that are backups or compiled classes
if ( bakPath.isChild(url) || outPath.isChild(url) || list[i].getName().endsWith("~") || list[i].getName().endsWith("jpx.local") ) {
continue;
}
if (bOnProject && ! this.isUnderVCS(fname,Actions.ON_DEP_OR_PEN_LIST)) {
// Not in P4
currentList.add(new VCSFileInfo(urltmp,new RevisionStatus(RevisionStatus.STATUS_NEW) ));
}else if (bOnProject && !this.isUnderVCS(fname,Actions.ON_PENDING_LIST) ) {
// Only on the depot list
currentList.add(new VCSFileInfo(urltmp,new RevisionStatus(RevisionStatus.STATUS_ON_DEPOT) ));
}else if(bOnProject){
// On the pending list
currentList.add(new VCSFileInfo(urltmp,new RevisionStatus(RevisionStatus.STATUS_ON_WORKSPACE) ));
}// endif on p4(yes, no, may be..)
}// endif is directory
}// end For
currentDir = new VCSFileInfo(url,new RevisionStatus(RevisionStatus.STATUS_ON_DEPOT));
List tmpList = (List)_FileStatus.get(currentDir);
if (currentList != null) {
_FileStatus.put(currentDir,currentList);
}
}
catch (Exception ex) {
ex.printStackTrace();
}
}
/**********************************************
* Name: searchKeyStr
*
* This methode seach in a text a key and when is done,
* the answer start in the next char TAB to the ENDLN
*
* Input: String the text
* String the key
*
* Output: String the answer from the key
*/
private String searchKeyStr(String text,String strKey){
try{
int posX1=0;
int posX2=0;
int posX3=0;
posX1=text.indexOf(strKey+":");
posX2=text.indexOf("\t",posX1);
posX3=text.indexOf("\n",posX2);
return text.substring(posX2+1,posX3);
}catch(Exception e){
return null;
}
}
/**********************************************
* This methode create a "SET" with all the <p>
* file(s) on P4
*
* Input: String the list of file on p4 format (depot-file#revision-number - local-path)
*
* Output: Set collection with all file on P4 (c:\toto\titi...)
*/
private Set setFiles(String sListOfFile){
try{
int posX1=0;
int posX2=0;
Set col = (Set)new HashSet();
do{
posX1=sListOfFile.indexOf("-",posX1);
posX2=sListOfFile.indexOf("\n",posX1);
posX1 += 2;
col.add(sListOfFile.substring(posX1,posX2).toLowerCase().replace('\\','/'));
}while((posX1=sListOfFile.indexOf("-",posX2)) != -1);
return col;
}catch(Exception e){
return null;
}
}
/***********************************************
* Add filse on the depot colection
*
* @param sFileToAdd List of files to add
*
*/
public void addFileOnDepot(StringBuffer sFileToAdd){
String sInput = sFileToAdd.toString();
StringTokenizer st = new StringTokenizer(sInput);
if (_FileOnP4 == null)
_FileOnP4 = new HashSet();
while(st.hasMoreTokens()){
String sFile = st.nextToken().trim().toLowerCase();
// Change the depot to the root
String sFiletmp = sFile.substring(getDepot().length());
sFile = getRoot()+ "/" + sFiletmp;
_FileOnP4.add(sFile);
}
}
/**********************************************
* This methode create a "SET" with all the <p>
* file(s) on P4 in the pending list
*
* Input: String the list of file on p4 format
* String the key
*
* Output: Set collection with all file on pending (//depot/...)
*/
private Set setFilesPending(String sListOfFile){
try{
int posX1=0;
int posX2=0;
int posX3=0;
Set col = (Set)new HashSet();
// First use of posX1 are index of key
posX1=sListOfFile.indexOf(this.KEY_FILES + ":");
posX2=sListOfFile.indexOf("//",posX1);
do{
posX3=sListOfFile.indexOf("\t",posX2);
col.add(sListOfFile.substring(posX2,posX3));
}while((posX2=sListOfFile.indexOf("//",posX3)) != -1);
return col;
}catch(Exception e){
return null;
}
}
/***********************************************
* Add filse on the pending colection
*
* @param sFileToAdd List of files to add
*
*/
public void addFileOnPending(StringBuffer sFileToAdd){
String sInput = sFileToAdd.toString();
StringTokenizer stTemp = new StringTokenizer(sInput);
if (_FileOnPending == null)
_FileOnPending = new HashSet();
while(stTemp!= null && stTemp.hasMoreTokens()){
_FileOnPending.add(stTemp.nextToken());
}
}
/***********************************************
* Remove file from the pending colection
*
* @param sFileToRemove List of files to add
*
*/
public void removeFileFromPending(StringBuffer sFileToRemove){
String sInput = sFileToRemove.toString();
StringTokenizer stTemp = new StringTokenizer(sInput);
if (_FileOnPending == null)
_FileOnPending = new HashSet();
while(stTemp.hasMoreTokens()){
_FileOnPending.remove(stTemp.nextToken());
}
}
/**
* For refresh the list of avaible file on P4 and reconfigure
*/
public void refresh(String ClientSpec,String sListOfFile, String sListPending){
initClass(ClientSpec, sListOfFile, sListPending);
}
/**
* Init the class, this methode should make a refresh
*/
private void initClass(String ClientSpec, String sListOfFile, String sListPending){
this.depot=searchKeyStr(ClientSpec,KEY_VIEW);
this.client=searchKeyStr(ClientSpec,KEY_CLIENT);
this.update=searchKeyStr(ClientSpec,KEY_UPDATE);
this.access=searchKeyStr(ClientSpec,KEY_ACCESS);
this.owner=searchKeyStr(ClientSpec,KEY_OWNER);
this.host=searchKeyStr(ClientSpec,KEY_HOST);
this.description=searchKeyStr(ClientSpec,KEY_DESCRIPTION);
this.root=searchKeyStr(ClientSpec,KEY_ROOT);
// Set the collection of file
_FileOnP4 = this.setFiles(sListOfFile);
// Set the collection of file pending
_FileOnPending = this.setFilesPending(sListPending);
}
/**
* For test only
*/
public static void main(String argv[]){
// For test only
/* P4ClientSpec my = new P4ClientSpec();
String s = "Change: new\r\n";
s = s+ "Client: nicolasj-njorand2\r\n";
s = s+ "User: nicolasj\r\n";
s = s+ "Status: new\r\n";
s = s+ "Description:\r\n";
s = s+ " <enter description here>\r\n";
s = s+ "Files:\r\n";
s = s+ " //depot/Tools/jBuilderOT/jBuilderVCS/projects/jBuilderVCS.html # add\r\n";
s = s+ " //depot/Tools/jBuilderOT/jBuilderVCS/src/com/jbase/jbuildervcs/Actions.java # edit\r\n";
s = s+ " //depot/Tools/jBuilderOT/jBuilderVCS/src/com/jbase/jbuildervcs/P4ClientSpec.java # edit\r\n";
s = s+ " //depot/Tools/jBuilderOT/jBuilderVCS/src/com/jbase/jbuildervcs/P4Cmd.java # edit\r\n";
s = s+ " //depot/Tools/jBuilderOT/jBuilderVCS/src/com/jbase/jbuildervcs/PerforceVCS.java # edit\r\n";
Set col = my.setFilesPending(s);
java.util.Iterator it = col.iterator();
for (;it.hasNext();){
String scol = (String)it.next();
System.out.println(scol);
System.out.println(col.contains((Object)new String("//depot/Tools/jBuilderOT/jBuilderVCS/src/com/jbase/jbuildervcs/PerforceVCS.java")));
}
*/
}
}