package bluej.groupwork.actions;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import bluej.Config;
import bluej.collect.DataCollector;
import bluej.groupwork.StatusHandle;
import bluej.groupwork.TeamUtils;
import bluej.groupwork.TeamworkCommand;
import bluej.groupwork.TeamworkCommandResult;
import bluej.groupwork.UpdateListener;
import bluej.groupwork.UpdateResults;
import bluej.groupwork.ui.ConflictsDialog;
import bluej.groupwork.ui.UpdateFilesFrame;
import bluej.pkgmgr.BlueJPackageFile;
import bluej.pkgmgr.Package;
import bluej.pkgmgr.PkgMgrFrame;
import bluej.pkgmgr.Project;
import bluej.pkgmgr.target.ClassTarget;
import bluej.pkgmgr.target.PackageTarget;
import bluej.pkgmgr.target.ReadmeTarget;
import bluej.pkgmgr.target.Target;
import bluej.utility.Debug;
import bluej.utility.DialogManager;
import bluej.utility.FXWorker;
import bluej.utility.JavaNames;
import javafx.stage.Window;
import threadchecker.OnThread;
import threadchecker.Tag;
| Action to update out-of-date files.
|
| <p>Before this action is enabled, setFilesToUpdate(), setFilesToForceUpdate()
| and setStatusHandle() must each be called.
|
| @author Kasper Fisker
|
@OnThread(Tag.FXPlatform)
public class UpdateAction
extends TeamAction{
private boolean includeLayout = true;
private UpdateFilesFrame updateFrame;
private UpdateWorker worker;
private Set<File> filesToUpdate;
private Set<File> filesToForceUpdate;
private StatusHandle statusHandle;
| A list of packages whose bluej.pkg file has been removed
|
private List<String> removedPackages;
public UpdateAction(UpdateFilesFrame updateFrame)
{
super(Config.getString("team.update"), false);
setShortDescription(Config.getString("tooltip.update"));
this.updateFrame = updateFrame;
}
| Set the files to be updated (changes merged if necessary).
| @files a Set of File
|
public void setFilesToUpdate(Set<File> files)
{
filesToUpdate = files;
}
| Set the files to be updated with a clean copy of the repository
| @files a Set of File
|
public void setFilesToForceUpdate(Set<File> files)
{
filesToForceUpdate = files;
}
| Set the status handle (which comes from a preceeding status operation).
|
public void setStatusHandle(StatusHandle statusHandle)
{
this.statusHandle = statusHandle;
}
@Override
protected void actionPerformed(Project project)
{
updateFrame.startProgress();
PkgMgrFrame.displayMessage(project, Config.getString("team.update.statusMessage"));
worker = new UpdateWorker(project, statusHandle, filesToUpdate, filesToForceUpdate);
worker.start();
updateFrame.disableLayoutCheck();
}
| Cancel the update, if it is presently running.
|
public void cancel()
{
if (worker != null) {
worker.abort();
}
setEnabled(true);
}
private class UpdateWorker
extends FXWorker implements UpdateListener
{
private Project project;
private TeamworkCommand command;
private TeamworkCommandResult result;
private boolean aborted;
public UpdateWorker(Project project, StatusHandle statusHandle,
Set<File> filesToUpdate, Set<File> filesToForceUpdate)
{
this.project = project;
command = statusHandle.updateTo(this, filesToUpdate, filesToForceUpdate);
}
@OnThread(Tag.Worker)
public Object construct()
{
removedPackages = new ArrayList<>();
result = command.getResult();
return result;
}
| (non-Javadoc)
| @see bluej.groupwork.UpdateListener#fileAdded(java.io.File)
|
@Override
@OnThread(Tag.FXPlatform)
public void fileModified(final File f)
{
String fileName = f.getName();
boolean isPkgFile = BlueJPackageFile.isPackageFileName(fileName);
if (! fileName.endsWith(".java") && ! fileName.endsWith(".class") && ! isPkgFile)
{
return;
}
String packageName = project.getPackageForFile(f);
if (packageName == null) {
return;
}
if (isPkgFile)
{
if (packageName.length() > 0)
{
String parentPackageName = JavaNames.getPrefix(packageName);
Package parentPackage = project.getCachedPackage(parentPackageName);
if (parentPackage != null)
{
Target t = parentPackage.addPackage(JavaNames.getBase(packageName));
parentPackage.positionNewTarget(t);
}
}
Package filePackage = project.getCachedPackage(packageName);
if (filePackage != null && includeLayout)
{
try
{
filePackage.reReadGraphLayout();
}
catch (IOException ioe)
{
Debug.reportError("Error re-reading package file (team update)", ioe);
}
}
}
else {
int n = fileName.lastIndexOf(".");
String name = fileName.substring(0, n);
if (! JavaNames.isIdentifier(name))
{
return;
}
Package pkg = project.getCachedPackage(packageName);
if (pkg == null)
{
return;
}
Target t = pkg.getTarget(name);
if (t == null)
{
ClassTarget ct = pkg.addClass(name);
pkg.positionNewTarget(ct);
DataCollector.addClass(pkg, ct);
return;
}
if (t instanceof ClassTarget)
{
((ClassTarget) t).reload();
}
}
}
| (non-Javadoc)
| @see bluej.groupwork.UpdateListener#fileRemoved(java.io.File)
|
@OnThread(Tag.FXPlatform)
public void fileRemoved(final File f)
{
String fileName = f.getName();
if (!fileName.endsWith(".java") &&
!fileName.endsWith(".class") &&
!BlueJPackageFile.isPackageFileName(fileName))
{
return;
}
String packageName = project.getPackageForFile(f);
if (packageName == null)
{
return;
}
if (BlueJPackageFile.isPackageFileName(fileName))
{
removedPackages.add(packageName);
}
else
{
int n = fileName.lastIndexOf(".");
String name = fileName.substring(0, n);
Package pkg = project.getCachedPackage(packageName);
if (pkg == null)
{
return;
}
Target t = pkg.getTarget(name);
if (!(t instanceof ClassTarget))
{
return;
}
ClassTarget ct = (ClassTarget) t;
if (ct.hasSourceCode() && !fileName.endsWith(".java"))
{
ct.markModified();
}
else
{
ct.remove();
}
}
}
| (non-Javadoc)
| @see bluej.groupwork.UpdateListener#dirRemoved(java.io.File)
|
@OnThread(Tag.FXPlatform)
public void dirRemoved(final File f)
{
String path = makeRelativePath(project.getProjectDir(), f);
String pkgName = path.replace(File.separatorChar, '.');
removedPackages.add(pkgName);
}
| (non-Javadoc)
| @see bluej.groupwork.UpdateListener#handleConflicts(bluej.groupwork.UpdateServerResponse)
|
@OnThread(Tag.FXPlatform)
public void handleConflicts(final UpdateResults updateServerResponse)
{
if (updateServerResponse.getConflicts().isEmpty()
&& updateServerResponse.getBinaryConflicts().isEmpty())
{
return;
}
| A list of files to replace with repository version
|
Set<File> filesToOverride = new HashSet<>();
for (Iterator<File> i = updateServerResponse.getBinaryConflicts().iterator();
i.hasNext(); ) {
File f = i.next();
if (BlueJPackageFile.isPackageFileName(f.getName())) {
filesToOverride.add(f);
}
else {
int answer = DialogManager.askQuestionFX(null,
"team-binary-conflict", new String[] {f.getName()
});
if (answer == 0) {
}
else {
filesToOverride.add(f);
}
}
}
updateServerResponse.overrideFiles(filesToOverride);
List<String> blueJconflicts = new LinkedList<String>();
List<String> nonBlueJConflicts = new LinkedList<String>();
List<Target> targets = new LinkedList<Target>();
for (Iterator<File> i = updateServerResponse.getConflicts().iterator(); i.hasNext(); )
{
File file = i.next();
String baseName = file.getName();
if (!BlueJPackageFile.isPackageFileName(baseName))
{
Target target = null;
if (baseName.endsWith(".java") || baseName.endsWith(".class"))
{
String pkg = project.getPackageForFile(file);
if (pkg != null)
{
String targetId = filenameToTargetIdentifier(baseName);
targetId = JavaNames.combineNames(pkg, targetId);
target = project.getTarget(targetId);
}
}
else if (baseName.equals("README.TXT"))
{
String pkg = project.getPackageForFile(file);
if (pkg != null)
{
String targetId = ReadmeTarget.README_ID;
targetId = JavaNames.combineNames(pkg, targetId);
target = project.getTarget(targetId);
}
}
String fileName = makeRelativePath(project.getProjectDir(), file);
if (target == null)
{
nonBlueJConflicts.add(fileName);
}
else
{
blueJconflicts.add(fileName);
targets.add(target);
if (target.getPackage().getUI() == null)
{
PkgMgrFrame.createFrame(target.getPackage(), PkgMgrFrame.getMostRecent());
}
}
}
}
if (!blueJconflicts.isEmpty() || !nonBlueJConflicts.isEmpty())
{
project.clearAllSelections();
project.selectTargetsInGraphs(targets);
Window stage = targets.isEmpty() ? null : targets.get(0).getPackage().getUI().getStage();
ConflictsDialog conflictsDialog = new ConflictsDialog(project, stage,
blueJconflicts, nonBlueJConflicts);
conflictsDialog.show();
}
else if (updateServerResponse.mergeCommitNeeded())
{
DialogManager.showMessageFX(null, "team-merge-commit-needed");
}
}
public void abort()
{
command.cancel();
aborted = true;
}
public void finished()
{
handleRemovedPkgs();
updateFrame.stopProgress();
if (! result.isError() && ! aborted) {
Set<File> files = new HashSet<File>();
files.addAll(filesToUpdate);
files.addAll(filesToForceUpdate);
DataCollector.teamUpdateProject(project, statusHandle.getRepository(), files);
PkgMgrFrame.displayMessage(project, Config.getString("team.update.statusDone"));
}
else {
PkgMgrFrame.displayMessage(project, "");
TeamUtils.handleServerResponseFX(result, updateFrame.asWindow());
}
if (! aborted) {
updateFrame.setVisible(false);
updateFrame.close();
setEnabled(true);
}
}
| If packages were removed by the update, remove them from the
| parent package graph.
|
@OnThread(Tag.FXPlatform)
private void handleRemovedPkgs()
{
for (Iterator<String> i = removedPackages.iterator(); i.hasNext(); ) {
String packageName = i.next();
String parentPackage = JavaNames.getPrefix(packageName);
String baseName = JavaNames.getBase(packageName);
File packageDir = JavaNames.convertQualifiedNameToFile(packageName, project.getProjectDir());
if (! packageDir.exists()) {
Package pkg = project.getCachedPackage(packageName);
if (pkg != null) {
pkg.closeAllEditors();
PkgMgrFrame frame = PkgMgrFrame.findFrame(pkg);
if (frame != null) {
frame.doClose(true, false);
}
project.removePackage(packageName);
}
pkg = project.getCachedPackage(parentPackage);
if (pkg != null) {
Target target = pkg.getTarget(baseName);
if (target instanceof PackageTarget) {
pkg.removeTarget(target);
}
}
}
}
}
}
| Strip the dot-suffix from a file name.
|
private String filenameToTargetIdentifier(String filename)
{
int lastDot = filename.lastIndexOf('.');
return filename.substring(0, lastDot);
}
| Make a relative path between a file and containing directory.
|
@OnThread(Tag.Any)
private static String makeRelativePath(File parent, File file)
{
String parentStr = parent.getAbsolutePath();
String filePath = file.getAbsolutePath();
if (filePath.startsWith(parentStr)) {
filePath = filePath.substring(parentStr.length() + 1);
}
return filePath;
}
}
top,
use,
map,
class UpdateAction
. UpdateAction
. setFilesToUpdate
. setFilesToForceUpdate
. setStatusHandle
. actionPerformed
. cancel
top,
use,
map,
class UpdateAction . UpdateWorker
. UpdateWorker
. construct
. fileModified
. fileRemoved
. dirRemoved
. handleConflicts
. abort
. finished
. handleRemovedPkgs
. filenameToTargetIdentifier
. makeRelativePath
548 neLoCode
+ 24 LoComm