// 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.guitools.qwin;
import com.qumasoft.qvcslib.AccessList;
import com.qumasoft.qvcslib.KeywordProperties;
import com.qumasoft.qvcslib.LabelInfo;
import com.qumasoft.qvcslib.LogFileHeaderInfo;
import com.qumasoft.qvcslib.LogfileInfo;
import com.qumasoft.qvcslib.MergedInfoInterface;
import com.qumasoft.qvcslib.RevisionHeader;
import com.qumasoft.qvcslib.RevisionInformation;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.swing.event.ListDataListener;
/**
* Revision and label information model.
* @author Jim Voris
*/
public class RevAndLabelInfoModel implements javax.swing.ListModel {
private static final String HEADER_TAG = "Header-";
private static final String LOCK_TAG = "Lock-";
private static final String LABEL_TAG = "Label-";
private static final String FLOATLABEL_TAG = "FloatLabel-";
private static final String PARSER_TAG = "-";
private static final String SEPARATOR_TAG = "Separator------------------------------------------------";
// The backing store here will be a linked list.
private List<String> revAndLabelList = Collections.synchronizedList(new LinkedList<String>());
private Map<ListDataListener, ListDataListener> listeners = Collections.synchronizedMap(new HashMap<ListDataListener, ListDataListener>());
private KeywordProperties keywordProperties;
private int wordWrapColumn;
private static final int DEFAULT_WORD_WRAP_COLUMN = 82;
/**
* Creates a new instance of RevAndLabelInfoModel.
*/
public RevAndLabelInfoModel() {
}
/**
* Create a new instance, using the given mergedInfo.
* @param mergedInfo the file from which we get the revision and label information.
*/
public RevAndLabelInfoModel(MergedInfoInterface mergedInfo) {
try {
keywordProperties = new KeywordProperties();
wordWrapColumn = keywordProperties.getWordWrapColumn();
} catch (Exception e) {
wordWrapColumn = DEFAULT_WORD_WRAP_COLUMN;
}
if (mergedInfo.getArchiveInfo() != null) {
addRevisionInformation(mergedInfo);
}
}
private void addRevisionInformation(MergedInfoInterface mergedInfo) {
LogfileInfo logfileInfo = mergedInfo.getLogfileInfo();
int revisionCount = logfileInfo.getLogFileHeaderInfo().getRevisionCount();
RevisionInformation revisionInformation = logfileInfo.getRevisionInformation();
AccessList accessList = new AccessList(logfileInfo.getLogFileHeaderInfo().getModifierList());
// Add header info at the beginning...
LogFileHeaderInfo logfileHeaderInfo = logfileInfo.getLogFileHeaderInfo();
revAndLabelList.add(HEADER_TAG + "File Description:");
addWordWrappedDescription(logfileHeaderInfo.getModuleDescription());
revAndLabelList.add(SEPARATOR_TAG);
for (int i = 0; i < revisionCount; i++) {
RevisionHeader revHeader = revisionInformation.getRevisionHeader(i);
String revisionCreator = accessList.indexToUser(revHeader.getCreatorIndex());
revAndLabelList.add(PARSER_TAG + revHeader.getRevisionString() + " check in time: " + revHeader.getCheckInDate().toString() + " by " + revisionCreator + "\n");
if (revHeader.isLocked()) {
String locker = accessList.indexToUser(revHeader.getLockerIndex());
revAndLabelList.add(LOCK_TAG + "Locked by: " + locker);
}
revAndLabelList.add(PARSER_TAG + "Workfile edit date: " + revHeader.getEditDate().toString());
addLabelInfo(i, mergedInfo);
addWordWrappedDescription(revHeader.getRevisionDescription());
revAndLabelList.add(SEPARATOR_TAG);
}
}
private void addLabelInfo(int revisionIndex, MergedInfoInterface mergedInfo) {
LabelInfo[] labelInfo = mergedInfo.getArchiveInfo().getLogfileInfo().getLogFileHeaderInfo().getLabelInfo();
if (labelInfo != null) {
RevisionHeader revisionHeader = mergedInfo.getArchiveInfo().getLogfileInfo().getRevisionInformation().getRevisionHeader(revisionIndex);
String revisionString = revisionHeader.getRevisionString();
int revisionDepth = revisionHeader.getDepth();
boolean isTipRevision = revisionHeader.isTip();
// Add any floating labels first.
if (isTipRevision) {
for (LabelInfo labelInfo1 : labelInfo) {
if (labelInfo1.isFloatingLabel() && (revisionDepth == labelInfo1.getDepth())) {
String labelRevisionString = labelInfo1.getLabelRevisionString();
if (revisionString.startsWith(labelRevisionString)) {
revAndLabelList.add(FLOATLABEL_TAG + labelInfo1.getLabelString());
}
}
}
}
for (LabelInfo labelInfo1 : labelInfo) {
String labelRevisionString = labelInfo1.getLabelRevisionString();
if (labelRevisionString.equals(revisionString)) {
revAndLabelList.add(LABEL_TAG + labelInfo1.getLabelString());
}
}
}
}
private void addWordWrappedDescription(String desc) {
byte[] descriptionBuffer = desc.getBytes();
// First convert any newline characters to spaces so we can put
// word wrap in whatever column the property file says.
for (int i = 0; i < descriptionBuffer.length; i++) {
if (descriptionBuffer[i] == '\n') {
descriptionBuffer[i] = ' ';
}
}
// Figure out where to word wrap.
int column = 0;
int preceedingSpaceIndex = 0;
int stringAnchorIndex = 0;
for (int i = 0; i < descriptionBuffer.length; i++, column++) {
if (descriptionBuffer[i] == ' ') {
if ((preceedingSpaceIndex > 0) && (column > wordWrapColumn)) {
String description = new String(descriptionBuffer, stringAnchorIndex, preceedingSpaceIndex - stringAnchorIndex);
revAndLabelList.add(PARSER_TAG + description);
column = 0;
stringAnchorIndex = preceedingSpaceIndex + 1;
}
preceedingSpaceIndex = i;
}
}
String finalLine = new String(descriptionBuffer, stringAnchorIndex, descriptionBuffer.length - stringAnchorIndex);
revAndLabelList.add(PARSER_TAG + finalLine);
}
/**
* Adds a listener to the list that's notified each time a change to the data model occurs.
*
* @param l the
* <code>ListDataListener</code> to be added
*
*/
@Override
public void addListDataListener(ListDataListener l) {
listeners.put(l, l);
}
/**
* Returns the value at the specified index.
*
* @param index the requested index
* @return the value at
* <code>index</code>
*
*/
@Override
public Object getElementAt(int index) {
return revAndLabelList.get(index);
}
/**
* Returns the length of the list.
*
* @return the length of the list
*
*/
@Override
public int getSize() {
return revAndLabelList.size();
}
/**
* Removes a listener from the list that's notified each time a change to the data model occurs.
*
* @param l the
* <code>ListDataListener</code> to be removed
*
*/
@Override
public void removeListDataListener(ListDataListener l) {
listeners.remove(l);
}
}