/******************************* Copyright notice ******************************* Copyright (C)2002 by Andrei Loskutov <loskutov@gmx.de>. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ********************************************************************************/ package adiag.model; import java.util.ArrayList; import java.util.HashMap; import adiag.Const; import adiag.util.Toolz; import adiag.view.VersionView; /** * The model - implementation of "revision" in Perforce * @author Andrei Loskutov */ public class Version { /** date of submit */ private String date; /** next version in same branch */ private Version next; /** version nummer */ private int versNumber; /** view of this version */ private VersionView view; /** previos version in same branch */ private Version prev; /** key is path + version number, value is Version */ private HashMap prevBranch; /** array with next versions in another branches */ private Version[] nextBranch; /** user of submit */ private String user; /** branch path */ private String path; /** submit change nummer */ private int change = -1; /** what kind of change is it? */ private String changeType; /** key is path + version number, value is string with change type */ private HashMap changeTypeFrom; /** lines of description */ private String[] description; /** used by making key id for version */ private static final String SPACER = "*"; private String versionAndChangeText; /** is information about this version received on direct way or through indirect * entires from another logs? * */ private boolean received; /** * Version constructor, create automatically new View for this version */ public Version() { super(); view = new VersionView(this); } /** * See return description * @return String for extra information on tooltip: both version and change number */ public String getVersionAndChangeText(){ if(versionAndChangeText == null || (isChangeNumOk() && versionAndChangeText.endsWith("-?"))){ StringBuffer sb = new StringBuffer(); sb.append(getVersNumber()).append("-"); if(!isChangeNumOk()){ sb.append("?"); } else { sb.append(getChange()); } versionAndChangeText = sb.toString(); } return versionAndChangeText; } /** is information about this version received on direct way or through indirect * entires from another logs? * @param ok true if directly received */ public void setReceived(boolean ok) { received = ok; } /** is information about this version received on direct way or through indirect * entires from another logs? * @return true if directly received */ public boolean isReceived() { return received; } /** * Add one more version to list of next branches * @param v Version of next branch */ public void addNextBranch(Version v) { if (v == null) { return; } if(nextBranch == null){ nextBranch = new Version[0]; } else { for (int i = 0; i < this.nextBranch.length; i++) { if (v.equals(nextBranch[i])) { return; } } } Version[] newNextBranch = new Version[nextBranch.length + 1]; System.arraycopy(nextBranch, 0, newNextBranch, 0, nextBranch.length); newNextBranch[nextBranch.length] = v; nextBranch = newNextBranch; } /** Compare two versions * @return true only if version number, path and change number are equals * @see java.lang.Object#equals(Object) */ public boolean equals(Object object) { // high performance fast path if (this == object){ return true; } // test object not null or other type else if (object == null || getClass() != object.getClass()){ return false; } // real value check is required Version theOther = (Version) object; if ((getVersNumber() == theOther.getVersNumber()) && (getPath() != null && getPath().equals(theOther.getPath())) && (getChange() == theOther.getChange())) { return true; } return false; } /** * See return description * @return -1 if change nummer is unknown, change number otherwise */ public int getChange() { return change; } /** * See return description * @return String change type or null if unknown */ public String getChangeType() { return changeType; } /** * See return description * @return null if not branched from this version or change * type */ public String getChangeTypeFrom(Version fromVerion) { String id = getID(fromVerion); if(changeTypeFrom == null){ return null; } else { return Const.getChangeType((String)changeTypeFrom.get(id)); } } /** * Method for make unique id's even if change number not known * @param v version * @return String unique id for version in/out of current branch */ private static String getID(Version v){ StringBuffer sb = new StringBuffer(v.getPath()); sb.append(SPACER).append(v.getVersNumber()); return sb.toString(); } /** See return description * @return date of change or null if not known */ public String getDate() { return date; } /** See return description * @return revision number of this version or 0 if not known */ public int getVersNumber() { return versNumber; } /** See return description * @return next Version in same branch */ public Version getNext() { return next; } /** * See return description * @return Version array with all branched versions */ public Version[] getNextBranch() { return nextBranch; } /** * Branch + file name, also full file path in depot * @return String path or null if not known */ public String getPath() { return path; } /** * short Branch + file name, also short file path in depot, * that differs on both strings, without any matched regions. * @param otherPath String to campare for common part of path */ public String getAbbreviatedPath(String otherPath) { if (this.path == null || otherPath == null || this.path.equals(otherPath)) { return path; } String p = path; // first slashes in path int idx = 0; if (path.startsWith("//")) { idx = 2; } // first occurence of next directory name idx = path.indexOf('/', idx); while (idx > 0 && path.regionMatches(0, otherPath, 0, idx)) { // we can cut here p = path.substring(idx); // go to next directory idx = path.indexOf('/', idx + 1); } return p; } /** * See return description * @return Previos version on same branch */ public Version getPrev() { return prev; } /** * See return description * @return user of change or null if not known */ public String getUser() { return user; } /** See return description * @return corresponding VersionView, cannot be null */ public VersionView getView() { return view; } /** * See return description * @return true if change number is set */ public boolean isChangeNumOk() { return getChange() >= 0; } /** * See return description * @return boolean true, if given version was ignored from current */ public boolean isIgnored(Version from) { return Const.TYPE_IGNORED.equals(getChangeTypeFrom(from)); } /** * See return description * @return true only if all of previos branches was ignored, * false if either was non branched version or one of branches * is not ignored */ public boolean isIgnored() { if(changeTypeFrom == null){ return false; } ArrayList al = new ArrayList(changeTypeFrom.values()); for (int i = 0; i < al.size(); i++) { if(!Const.TYPE_IGNORED.equals(al.get(i))){ return false; } } return al.size()>0; } /** * Set new changenummer * @param newChange int for new change number, -1 for "not set" */ public void setChange(int newChange) { change = newChange; } /** * Set new change type * @param newChangeType one of "on" - actions, i.e. "edit on" or "copy on", etc */ public void setChangeType(String newChangeType) { changeType = newChangeType; } /** Set date of change * @param newDate String with date of change, will be not parsed to Date class */ public void setDate(String newDate) { date = newDate; } /** Set version number * @param newNumber int version number */ public void setVersNumber(int newNumber) { versNumber = newNumber; } /** * Set next version on same branch * @param newNext next version on same branch */ public void setNext(Version newNext) { next = newNext; } /** * Set branch + file name, also full file path in depot * @param newPath branch + file name, also full file path in depot */ public void setPath(String newPath) { path = newPath; } /** * Set previos version on same branch * @param newPrev previos version on same branch */ public void setPrev(Version newPrev) { prev = newPrev; } /** * Method addPrevBranch add one more previos branch version to the list * @param newPrevBranch previos branch version * @param changeType previos branch change type, i.e. "ignored" or "merge" */ public void addPrevBranch(Version newPrevBranch, String changeType) { if(prevBranch == null){ prevBranch = new HashMap(2); changeTypeFrom = new HashMap(2); } String id = getID(newPrevBranch); if(prevBranch.get(id) != null){ return; } else { prevBranch.put(id, newPrevBranch); changeTypeFrom.put(id, changeType); } } /** * Set change user * @param newUser String change user */ public void setUser(String newUser) { user = newUser; } /** * See return description * @param html true for HTML - formatted output, false for plaintext * @return Formatted string with full available P4 information about this Version */ private String toSpecialString(boolean html) { String newline = !html ? "\n" : "\n<p>"; String stopHtml = "</font></td></tr></table></body></html>"; StringBuffer sb = new StringBuffer(); if(html){ float width = (Const.CHARACTER_H_SIZE - 1) * 70; //System.out.println(width); sb.append("<html><body bgcolor=#F8FCE0><table width='"); sb.append(width).append("'><tr><td><font size=-1 face=Arial,Verdana,Helvetica>"); } sb.append(newline).append(getPath()); sb.append(newline).append("#"); sb.append(versNumber).append(", ").append("change "); if (change > 0) { sb.append(change); } else { sb.append("?"); } sb.append(" on "); if (getDate() != null) { sb.append(getDate()); } else { sb.append("?"); } sb.append(" by "); if (getUser() != null) { sb.append(getUser()); } else { sb.append("?"); } if (prevBranch != null) { ArrayList al = new ArrayList(prevBranch.keySet()); String key = ""; Version nv; for (int i = 0; i < al.size(); i++) { key = (String)al.get(i); nv = (Version)prevBranch.get(key); sb.append(newline).append(getChangeTypeFrom(nv)); sb.append(" from: ").append(nv.getPath()).append(", "); sb.append("#").append(nv.getVersNumber()); sb.append(", ").append("change "); if (nv.getChange() > 0) { sb.append(nv.getChange()); } else { sb.append("?"); } } } if (nextBranch != null) { for (int i = 0; i < nextBranch.length; i++) { sb.append(newline).append(nextBranch[i].getChangeTypeFrom(this)); sb.append(" into: ").append(nextBranch[i].getPath()).append(", "); sb.append("#").append(nextBranch[i].getVersNumber()); sb.append(", ").append("change "); if (nextBranch[i].getChange() > 0) { sb.append(nextBranch[i].getChange()); } else { sb.append("?"); } } } sb.append(newline); //sb.append("Descr.:"); if (description != null) { for (int i = 0; i < description.length; i++) { sb.append(description[i]); if (i + 1 < description.length) { sb.append(newline); } } } else { sb.append("???"); } if(html){ sb.append(stopHtml); } return sb.toString(); } /** * See return description * @return HTML Formatted string with full available P4 information about this Version */ public String toHtmlString() { return toSpecialString(true); } /** * See return description * @return plain-text formatted string with full available P4 information about this Version */ public String toString() { return toSpecialString(false); } /** * Add one more description line for change * @param description String description line */ public void addDescriptionLine(String description) { if (description == null) { return; } if (this.description == null) { this.description = new String[0]; } int size = this.description.length; String[] newd = new String[size + 1]; if (size > 0) { if (Toolz.count(this.description, description) <= 0) { System.arraycopy(this.description, 0, newd, 0, size); } else { return; } } newd[size] = description; this.description = newd; } /** * Get description lines for change * @return all known description lines for change, or empty array, never null */ public String[] getDescription() { return description == null ? new String[0] : description; } }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#4 | 2735 | andrei_loskutov | sources are now included to binary distribution at http://andrei.gmxhome.de/perforce/index.html | ||
#3 | 2552 | andrei_loskutov | 1.3.0.4 changes | ||
#2 | 2460 | andrei_loskutov |
1) Change configuration: always reed properties 2) Change password store to hex format/password field 3) Create standalone/not standalone state for new branchview eclipse wrapper 4) Refactor all main classes to remove cyclic package dependency 5) Add workaround to fix new JDK 1.4.1 Swing bugs on JScrollPane/JViewPort 6) Add dispose methods to panel/connector 7) Minor internal GUI fixes/refactorings |
||
#1 | 2222 | andrei_loskutov |
#13.10.2002 22:16 Revision 1.2.1 1) Documentation task is finished... Yes!!! 2) New feature: copy P4 depot path 3) Some small fixes to menu shortkeys belongs ctrl + c and ctrl + d 4) Clipboard fix because of JDK 1.2 - 1.3 bug 5) Smallest refactoring on some methods. 6) Html help updated |