/* 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.operation;
import com.qumasoft.guitools.qwin.QWinFrame;
import com.qumasoft.guitools.qwin.QWinUtility;
import com.qumasoft.qvcslib.ClientExpansionContext;
import com.qumasoft.qvcslib.FileMerge;
import com.qumasoft.qvcslib.MergedInfoInterface;
import com.qumasoft.qvcslib.QVCSException;
import com.qumasoft.qvcslib.QVCSOperationException;
import com.qumasoft.qvcslib.UserLocationProperties;
import com.qumasoft.qvcslib.Utility;
import com.qumasoft.qvcslib.WorkfileDigestManager;
import com.qumasoft.qvcslib.WorkfileInfo;
import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import javax.swing.JOptionPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
/**
* Merge a file.
* @author Jim Voris
*/
public class OperationMergeFile extends OperationBaseClass {
/**
* Create a merge file operation.
* @param fileTable the file table.
* @param serverName the server name.
* @param projectName the project name.
* @param viewName the view name.
* @param userLocationProperties user location properties.
*/
public OperationMergeFile(JTable fileTable, String serverName, String projectName, String viewName, UserLocationProperties userLocationProperties) {
super(fileTable, serverName, projectName, viewName, userLocationProperties);
}
@Override
public void executeOperation() {
if (getFileTable() != null) {
try {
final List mergedInfoArray = getSelectedFiles();
final int fileCount = mergedInfoArray.size();
if (mergedInfoArray.size() > 0) {
// Run the update on the Swing thread.
Runnable later = new Runnable() {
@Override
public void run() {
// Ask the user to confirm the merge operation.
int answer = JOptionPane.showConfirmDialog(QWinFrame.getQWinFrame(), "Merge the selected file(s)?", "Merge Selected Workfiles",
JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE);
if (answer == JOptionPane.YES_OPTION) {
Iterator it = mergedInfoArray.iterator();
while (it.hasNext()) {
MergedInfoInterface mergedInfo = (MergedInfoInterface) it.next();
if ((!mergedInfo.getAttributes().getIsBinaryfile())
&& (mergedInfo.getStatusIndex() == MergedInfoInterface.MERGE_REQUIRED_STATUS_INDEX)) {
try {
mergeFile(mergedInfo, fileCount);
} catch (IOException e) {
QWinUtility.logProblem(Level.SEVERE, Utility.expandStackTraceToString(e));
} catch (QVCSException e) {
QWinUtility.logProblem(Level.WARNING, Utility.expandStackTraceToString(e));
}
} else {
if (mergedInfo.getAttributes().getIsBinaryfile()) {
QWinUtility.logProblem(Level.INFO, "Skipping merge of binary file: " + mergedInfo.getShortWorkfileName());
}
}
}
QWinFrame.getQWinFrame().refreshCurrentView();
}
}
};
SwingUtilities.invokeLater(later);
}
} catch (Exception e) {
QWinUtility.logProblem(Level.WARNING, "OperationMergeFile caught exception: " + e.getClass().toString() + " " + e.getLocalizedMessage());
QWinUtility.logProblem(Level.WARNING, Utility.expandStackTraceToString(e));
}
}
}
private void mergeFile(MergedInfoInterface mergedInfo, final int fileCount) throws IOException, QVCSException {
// Get the base revision string for the current workfile.
String baseRevisionString = WorkfileDigestManager.getInstance().getDigestWorkfileInfo(mergedInfo.getWorkfileInfo()).getWorkfileRevisionString();
String currentDefaultRevisionString = mergedInfo.getDefaultRevisionString();
// Get workfile buffer... not keyword expanded.
byte[] baseBuffer = mergedInfo.getRevisionAsByteArray(baseRevisionString);
byte[] defaultBuffer = mergedInfo.getRevisionAsByteArray(currentDefaultRevisionString);
int baseBufferRevisionIndex = mergedInfo.getLogfileInfo().getRevisionInformation().getRevisionIndex(baseRevisionString);
int defaultBufferRevisionIndex = mergedInfo.getLogfileInfo().getRevisionInformation().getRevisionIndex(currentDefaultRevisionString);
if ((baseBuffer != null) && (defaultBuffer != null)) {
ClientExpansionContext baseContext = new ClientExpansionContext(getServerName(), QWinFrame.getQWinFrame().getUserProperties(),
QWinFrame.getQWinFrame().getUserLocationProperties(), baseBufferRevisionIndex, null, true);
File expandedBaseBufferFile = Utility.expandBuffer(baseBuffer, mergedInfo, baseContext);
ClientExpansionContext defaultContext = new ClientExpansionContext(getServerName(), QWinFrame.getQWinFrame().getUserProperties(),
QWinFrame.getQWinFrame().getUserLocationProperties(), defaultBufferRevisionIndex, null, true);
File expandedDefaultBufferFile = Utility.expandBuffer(defaultBuffer, mergedInfo, defaultContext);
File currentWorkFile = mergedInfo.getWorkfile();
File afterMergeWorkFile = new File(currentWorkFile.getCanonicalPath() + ".qvcsAfterMerge");
FileMerge instance = new FileMerge();
boolean result;
try {
result = instance.mergeFiles(expandedBaseBufferFile.getCanonicalPath(), expandedDefaultBufferFile.getCanonicalPath(), currentWorkFile.getCanonicalPath(),
afterMergeWorkFile.getCanonicalPath());
if (result) {
// Rename the current workfile to a backup copy.
File beforeMergeWorkFile = new File(currentWorkFile.getCanonicalPath() + ".qvcsBeforeMerge");
beforeMergeWorkFile.delete();
currentWorkFile.renameTo(beforeMergeWorkFile);
// Rename the merged workfile to be the new workfile
currentWorkFile = mergedInfo.getWorkfile();
afterMergeWorkFile.renameTo(currentWorkFile);
// Create a new workfileInfo that we use in the case that the user saves the result of the merge...
WorkfileInfo workfileInfo = new WorkfileInfo(mergedInfo.getFullWorkfileName(), mergedInfo.getAttributes().getIsExpandKeywords(),
mergedInfo.getAttributes().getIsBinaryfile(), getProjectName());
Date now = new Date();
workfileInfo.setFetchedDate(now.getTime());
workfileInfo.setWorkfileRevisionString(currentDefaultRevisionString);
// Update the Workfile digest manager.
WorkfileDigestManager.getInstance().updateWorkfileDigestForMerge(defaultBuffer, workfileInfo, mergedInfo.getArchiveDirManager().getProjectProperties());
}
} catch (QVCSOperationException e) {
// We expect a QVCSOperationException to be thrown to flag the overlap.
// If they are only merging one file, then we can display a TextPane to warn them about the overlap.
if (fileCount == 1) {
JOptionPane.showConfirmDialog(QWinFrame.getQWinFrame(), e.getLocalizedMessage(), "Merge: Overlap detected!", JOptionPane.WARNING_MESSAGE);
}
}
}
}
}