// 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.IOException;
import java.io.RandomAccessFile;
import java.text.DecimalFormat;
import java.util.Objects;
/**
* Revision Descriptor.
* @author Jim Voris
*/
public class RevisionDescriptor implements java.io.Serializable, java.lang.Comparable {
private static final long serialVersionUID = 6979959250553685828L;
private final int elementCount;
private final CommonShort csElementCount = new CommonShort();
private final CommonShort csRevisionAttributes = new CommonShort();
private MajorMinorRevisionPair[] revisionPairs;
private transient String sortableString = null;
/**
* Create a revision descriptor.
* @param elementCnt the number of elements in this descriptor.
* @param majorMinorArray the major/minor array that will be used to initialize the descriptor.
*/
public RevisionDescriptor(int elementCnt, MajorMinorRevisionPair[] majorMinorArray) {
elementCount = elementCnt;
if (elementCount > 0) {
csElementCount.setValue(elementCount);
csRevisionAttributes.setValue(0);
revisionPairs = new MajorMinorRevisionPair[elementCount];
for (int i = 0; i < elementCount; i++) {
revisionPairs[i] = new MajorMinorRevisionPair(majorMinorArray[i].getMajorNumber(), majorMinorArray[i].getMinorNumber());
}
}
}
/**
* Create a revision descriptor with the given number of elements.
* @param elementCnt the element count for this descriptor.
*/
public RevisionDescriptor(int elementCnt) {
elementCount = elementCnt;
}
/**
* Create a revision descriptor for the given revision and revision parent.
* @param newRevision the revision for which this will be the descriptor.
* @param parentRevision the revision's parent revision.
*/
public RevisionDescriptor(RevisionHeader newRevision, RevisionHeader parentRevision) {
elementCount = newRevision.getDepth() + 1;
if (elementCount > 0) {
csElementCount.setValue(elementCount);
csRevisionAttributes.setValue(0);
revisionPairs = new MajorMinorRevisionPair[elementCount];
RevisionDescriptor parentRevisionDescriptor = parentRevision.getRevisionDescriptor();
MajorMinorRevisionPair[] parentRevisionPairs = parentRevisionDescriptor.revisionPairs;
for (int i = 0; i < parentRevisionDescriptor.getElementCount(); i++) {
revisionPairs[i] = new MajorMinorRevisionPair(parentRevisionPairs[i].getMajorNumber(), parentRevisionPairs[i].getMinorNumber());
}
revisionPairs[elementCount - 1] = new MajorMinorRevisionPair(newRevision.getMajorNumber(), newRevision.getMinorNumber());
}
}
/**
* A Copy constructor.
* @param revisionDescriptorToCopy the descriptor to copy.
*/
public RevisionDescriptor(final RevisionDescriptor revisionDescriptorToCopy) {
elementCount = revisionDescriptorToCopy.elementCount;
if (elementCount > 0) {
csElementCount.setValue(elementCount);
csRevisionAttributes.setValue(0);
revisionPairs = new MajorMinorRevisionPair[elementCount];
for (int i = 0; i < elementCount; i++) {
revisionPairs[i] = new MajorMinorRevisionPair(revisionDescriptorToCopy.revisionPairs[i].getMajorNumber(),
revisionDescriptorToCopy.revisionPairs[i].getMinorNumber());
}
}
}
/**
* A convenient toString.
* @return a convenient string representation of this revision descriptor.
*/
@Override
public String toString() {
StringBuilder returnString = new StringBuilder();
for (int i = 0; i < elementCount; i++) {
if (i != 0) {
returnString.append(".");
}
returnString.append(revisionPairs[i]);
}
return returnString.toString();
}
/**
* Return a sortable String representation for this revision descriptor.
* @return a sortable String representation for this revision descriptor.
*/
public synchronized String toSortableString() {
if (sortableString == null) {
DecimalFormat formatter = new DecimalFormat("0000");
StringBuilder resultBuffer = new StringBuilder();
for (int i = 0; i < elementCount; i++) {
resultBuffer.append(formatter.format(revisionPairs[i].getMajorNumber()));
resultBuffer.append(formatter.format(revisionPairs[i].getMinorNumber()));
}
sortableString = resultBuffer.toString();
}
return sortableString;
}
/**
* Read the revision descriptor information from the archive file.
* @param inStream the stream to read from.
* @throws IOException for read problems.
*/
public void read(RandomAccessFile inStream) throws IOException {
if (elementCount > 0) {
csElementCount.read(inStream);
csRevisionAttributes.read(inStream);
revisionPairs = new MajorMinorRevisionPair[elementCount];
for (int i = 0; i < elementCount; i++) {
revisionPairs[i] = new MajorMinorRevisionPair();
revisionPairs[i].read(inStream);
}
// There's a bug in the archive format. So read (and discard) some stuff.
MajorMinorRevisionPair pair = new MajorMinorRevisionPair();
pair.read(inStream);
int junkInteger = inStream.readInt();
}
}
/**
* Write the revision descriptor to the archive file.
* @param outStream the stream to write to.
* @throws IOException for write problems.
*/
public void write(RandomAccessFile outStream) throws IOException {
if (elementCount > 0) {
csElementCount.write(outStream);
csRevisionAttributes.write(outStream);
for (int i = 0; i < elementCount; i++) {
revisionPairs[i].write(outStream);
}
// There's a bug in the archive format. So write some stuff.
MajorMinorRevisionPair pair = new MajorMinorRevisionPair();
pair.write(outStream);
outStream.writeInt(0);
}
}
/**
* Get the trunk minor number.
* @return the trunk minor number.
*/
public int getTrunkMinorNumber() {
return revisionPairs[0].getMinorNumber();
}
/**
* Get the element count.
* @return the element count.
*/
public int getElementCount() {
return elementCount;
}
@Override
public int compareTo(Object o) {
RevisionDescriptor otherDescriptor = (RevisionDescriptor) o;
String ourSortable = toSortableString();
String otherSortable = otherDescriptor.toSortableString();
return ourSortable.compareTo(otherSortable);
}
@Override
public int hashCode() {
// Guarantee the sortable string has been set.
toSortableString();
// <editor-fold>
int hash = 7;
hash = 53 * hash + Objects.hashCode(this.sortableString);
// </editor-fold>
return hash;
}
@Override
public boolean equals(Object obj) {
// Guarantee the sortable string has been set.
toSortableString();
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final RevisionDescriptor other = (RevisionDescriptor) obj;
return Objects.equals(this.sortableString, other.sortableString);
}
/**
* Get the revision pairs of this revision descriptor.
* @return the revision pairs of this revision descriptor.
*/
public MajorMinorRevisionPair[] getRevisionPairs() {
return revisionPairs;
}
}