// Copyright 2004-2014 Jim Voris
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package com.qumasoft.qvcslib;
import java.io.RandomAccessFile;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Revision information. This class is a convenience wrapper around the revision information contained in a QVCS archive file.
* @author Jim Voris
*/
public class RevisionInformation implements java.io.Serializable {
private static final long serialVersionUID = 1738246718497875838L;
private final AccessList accessList;
private final AccessList modifierList;
private final RevisionHeader[] revHeaders;
/** Create our logger object */
private static final Logger LOGGER = Logger.getLogger("com.qumasoft.qvcslib");
/**
* Construct a revision information instance.
* @param revisionCount the number of revisions.
* @param accessLst the access list.
* @param modifierLst the modifier list.
*/
public RevisionInformation(int revisionCount, AccessList accessLst, AccessList modifierLst) {
revHeaders = new RevisionHeader[revisionCount];
accessList = accessLst;
modifierList = modifierLst;
}
/**
* Get a given revision header.
* @param index the revision header's index. Index of 0 is the newest revision.
* @return the revision header associated with the given index.
*/
public RevisionHeader getRevisionHeader(int index) {
RevisionHeader revHeader = null;
if (index < revHeaders.length) {
revHeader = revHeaders[index];
}
return revHeader;
}
/**
* Read revision information from the QVCS archive. This routine assumes the file is positioned at the beginning of the revision information.
* @param inStream the RandomAccessFile stream that we read from.
* @return true if the revision information was read successfully; false otherwise.
*/
public boolean read(RandomAccessFile inStream) {
boolean returnValue = true;
RevisionHeader[] revisionBranches = new RevisionHeader[QVCSConstants.QVCS_MAXIMUM_BRANCH_DEPTH];
MajorMinorRevisionPair[] majorMinorArray = new MajorMinorRevisionPair[QVCSConstants.QVCS_MAXIMUM_BRANCH_DEPTH];
for (int i = 0; i < revHeaders.length; i++) {
revHeaders[i] = new RevisionHeader(accessList, modifierList);
revHeaders[i].read(inStream, majorMinorArray);
revHeaders[i].setRevisionIndex(i);
// Allow the child revision to keep track of its parent.
if (i > 0) {
if (revHeaders[i].getDepth() == 0) {
revHeaders[i].setParentRevisionHeader(revisionBranches[0]);
} else if (revHeaders[i].getDepth() == revHeaders[i - 1].getDepth()) {
if (revHeaders[i].getMajorNumber() == revHeaders[i - 1].getMajorNumber()) {
// This revision is on the same branch as the immediately preceeding revision.
revHeaders[i].setParentRevisionHeader(revHeaders[i - 1]);
} else {
// This is the beginning of another branch that has the same
// 'parent' as a sibling branch.
revHeaders[i].setParentRevisionHeader(revisionBranches[revHeaders[i].getDepth() - 1]);
}
} else {
// This revision is on a different branch than the preceeding revision...
if (revHeaders[i].getDepth() > revHeaders[i - 1].getDepth()) {
// This revision is the first revision on a branch... so it's parent
// is the immediately preceeding branch point revision.
revHeaders[i].setParentRevisionHeader(revHeaders[i - 1]);
} else {
// This revision is closer to the TRUNK than the immediately preceeding
// revision. It's parent revision is the most recently encountered
// revision that was at the same depth as this revision.
revHeaders[i].setParentRevisionHeader(revisionBranches[revHeaders[i].getDepth()]);
}
}
}
// Save the most recently encountered revision for a given depth.
revisionBranches[revHeaders[i].getDepth()] = revHeaders[i];
}
return returnValue;
}
/**
* Get the modifier list.
* @return the modifier list.
*/
public AccessList getModifierList() {
return modifierList;
}
/**
* Get the access list.
* @return the access list.
*/
AccessList getAccessList() {
return accessList;
}
/**
* Get the String of the revision locked by userName.
*
* @param userName the QVCS user to check for locks
* @return the String for that user's locked revision. null if the user holds no locks.
*/
public String getLockedRevision(String userName) {
String lockedRevision = null;
try {
for (RevisionHeader revHeader : revHeaders) {
if (revHeader.isLocked()) {
if (0 == getModifierList().indexToUser(revHeader.getLockerIndex()).compareTo(userName)) {
lockedRevision = revHeader.getRevisionString();
}
}
}
} catch (QVCSRuntimeException e) {
// Nothing to do here. The user's has no locked revisions
// as far as we are concerned.
LOGGER.log(Level.FINE, "No locked revisions: " + e.getLocalizedMessage());
}
return lockedRevision;
}
/**
* Convenience toString to report on the revision header information.
* @return report on the revision header information.
*/
@Override
public String toString() {
StringBuilder string = new StringBuilder();
string.append("\n");
for (RevisionHeader revisionHeader : revHeaders) {
string.append("------------------\n");
string.append(revisionHeader.toString());
}
return string.toString();
}
/**
* Return the index for the given revision string. Return a -1 if the revision string is not found.
*
* @param revisionString the revision to search for.
* @return return the index associated with the given revision string.
*/
public int getRevisionIndex(String revisionString) {
int returnedIndex = -1;
for (int i = 0; i < revHeaders.length; i++) {
RevisionHeader revHeader = revHeaders[i];
String currentRevString = revHeader.getRevisionString();
if (0 == revisionString.compareTo(currentRevString)) {
returnedIndex = i;
break;
}
}
return returnedIndex;
}
/**
* Update a given revision header.
* @param revisionIndex the revision index for the header that is to be updated.
* @param updatedRevHeader the updated header.
*/
public void updateRevision(int revisionIndex, RevisionHeader updatedRevHeader) {
revHeaders[revisionIndex] = updatedRevHeader;
}
}