/* 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.AbstractProjectProperties;
import com.qumasoft.qvcslib.DefaultServerProperties;
import com.qumasoft.qvcslib.DirectoryManagerFactory;
import com.qumasoft.qvcslib.QVCSConstants;
import com.qumasoft.qvcslib.QVCSServerNamesFilter;
import com.qumasoft.qvcslib.RemoteProjectProperties;
import com.qumasoft.qvcslib.RemoteViewProperties;
import com.qumasoft.qvcslib.ServerManager;
import com.qumasoft.qvcslib.ServerProperties;
import com.qumasoft.qvcslib.response.ServerResponseListProjects;
import com.qumasoft.qvcslib.response.ServerResponseListViews;
import com.qumasoft.qvcslib.response.ServerResponseProjectControl;
import com.qumasoft.qvcslib.TimerManager;
import com.qumasoft.qvcslib.TransportProxyFactory;
import com.qumasoft.qvcslib.Utility;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Timer;
import java.util.TimerTask;
import java.util.TreeMap;
import java.util.logging.Level;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
/**
* Project tree model.
* @author Jim Voris
*/
public class ProjectTreeModel implements ChangeListener {
private javax.swing.tree.DefaultTreeModel projectTreeModel;
// A map of the servers we know about.
private final TreeMap<String, ServerTreeNode> serverNodeMap;
// A map of the projects that we know about.
private final TreeMap<String, ProjectTreeNode> projectNodeMap;
// Timer and TimerTask we use to aggregate model updates so screen won't
// flicker when we get a ton of state changed calls in succession.
private final Timer timerDaemon;
private TimerTask notifyTask;
private static final long UPDATE_DELAY = 300;
private final Object modelSyncObject = new Object();
/**
* Used to capture the deepest existing parent so when a subproject is added we don't need to refresh the entire view's tree, but can update the model from this node and below.
*/
private DefaultMutableTreeNode deepestParent;
/**
* Used to hold the directory node we select after receiving all the directories from the server.
*/
private DefaultMutableTreeNode pendingDirectoryNode;
/**
* Creates new ProjectTreeModel.
*/
public ProjectTreeModel() {
this.projectNodeMap = new TreeMap<>();
this.serverNodeMap = new TreeMap<>();
loadModel();
TransportProxyFactory.getInstance().addChangeListener(this);
ServerManager.getServerManager().addChangeListener(this);
// Create our daemon timer task so we can aggregate updates.
timerDaemon = TimerManager.getInstance().getTimer();
}
javax.swing.tree.DefaultTreeModel getTreeModel() {
return projectTreeModel;
}
@Override
public void stateChanged(final javax.swing.event.ChangeEvent changeEvent) {
// Install the thread tracking repaint manager.
Runnable stateChangedTask = new Runnable() {
@Override
public void run() {
Object o = changeEvent.getSource();
if (o instanceof ServerResponseProjectControl) {
ServerResponseProjectControl controlMessage = (ServerResponseProjectControl) o;
if (controlMessage.getAddFlag()) {
// Add node to the tree.
addSubProject(controlMessage.getServerName(), controlMessage.getProjectName(), controlMessage.getViewName(), controlMessage.getDirectorySegments());
QWinUtility.logProblem(Level.FINE, "Adding subproject; server: " + controlMessage.getServerName() + " for project: " + controlMessage.getProjectName()
+ " view name: " + controlMessage.getViewName() + " appended path: " + buildAppendedPath(controlMessage.getDirectorySegments()));
} else if (controlMessage.getRemoveFlag()) {
ViewTreeNode viewTreeNode = findProjectViewTreeNode(controlMessage.getServerName(), controlMessage.getProjectName(), controlMessage.getViewName());
if ((controlMessage.getDirectorySegments() == null) || (controlMessage.getDirectorySegments().length == 0)) {
// Remove node from the tree.
if (viewTreeNode != null) {
viewTreeNode.removeAllChildren();
DefaultServerTreeNode rootNode = (DefaultServerTreeNode) getTreeModel().getRoot();
ProjectTreeControl.getInstance().selectRootNode();
projectTreeModel.nodeStructureChanged(rootNode);
QWinFrame.getQWinFrame().clearUsernamePassword(controlMessage.getServerName());
}
QWinUtility.logProblem(Level.FINE, "Removing project '" + controlMessage.getProjectName() + "' from project tree");
} else {
deleteSubprojectNode(viewTreeNode, viewTreeNode.getProjectProperties(), controlMessage.getDirectorySegments());
QWinUtility.logProblem(Level.INFO, "Removing directory '" + controlMessage.getProjectName() + "' from project tree");
}
}
} else if (o instanceof ServerResponseListProjects) {
ServerResponseListProjects serverResponseListProjects = (ServerResponseListProjects) o;
TreeNode changedNode = loadRemoteProjects(serverResponseListProjects);
QWinFrame.getQWinFrame().setIgnoreTreeChanges(true);
if (changedNode != null) {
projectTreeModel.nodeStructureChanged(changedNode);
DefaultMutableTreeNode node = (DefaultMutableTreeNode) changedNode;
QWinFrame.getQWinFrame().getTreeControl().getProjectJTreeControl().expandPath(new TreePath(node.getPath()));
// Select the project/view that was active the last time the
// user ran the program.
String projectName = QWinFrame.getQWinFrame().getUserProperties().getMostRecentProjectName();
if (projectName != null && projectName.length() > 0) {
TreeNode projectNode = findProjectTreeNode(serverResponseListProjects.getServerName(), projectName);
ProjectTreeControl.getInstance().selectNode(projectNode);
}
}
QWinFrame.getQWinFrame().setIgnoreTreeChanges(false);
} else if (o instanceof ServerResponseListViews) {
ServerResponseListViews serverResponseListViews = (ServerResponseListViews) o;
TreeNode changedNode = loadRemoteViews(serverResponseListViews);
QWinFrame.getQWinFrame().setIgnoreTreeChanges(true);
if (changedNode != null) {
projectTreeModel.nodeStructureChanged(changedNode);
DefaultMutableTreeNode node = (DefaultMutableTreeNode) changedNode;
QWinFrame.getQWinFrame().getTreeControl().getProjectJTreeControl().expandPath(new TreePath(node.getPath()));
// Discard any DirectoryManagers that we have for this project...
// They will get rebuilt as the user navigates into the project.
DirectoryManagerFactory.getInstance().discardDirectoryManagersForProject(serverResponseListViews.getServerName(), serverResponseListViews.getProjectName());
// Select the project/view that was active the last time the
// user ran the program.
String projectName = QWinFrame.getQWinFrame().getUserProperties().getMostRecentProjectName();
String viewName = QWinFrame.getQWinFrame().getUserProperties().getMostRecentViewName();
if ((projectName != null && projectName.length() > 0)
&& (viewName != null && viewName.length() > 0)) {
TreeNode directoryNode = findProjectViewTreeNode(serverResponseListViews.getServerName(), projectName, viewName);
ProjectTreeControl.getInstance().selectNode(directoryNode);
}
}
QWinFrame.getQWinFrame().setIgnoreTreeChanges(false);
}
}
};
SwingUtilities.invokeLater(stateChangedTask);
}
private void addSubProject(final String serverName, final String projectName, final String viewName, String[] segments) {
ViewTreeNode viewNode;
synchronized (modelSyncObject) {
viewNode = findProjectViewTreeNode(serverName, projectName, viewName);
if (viewNode != null) {
addSubprojectNode(viewNode, viewNode.getProjectProperties(), segments);
String appendedPath = buildAppendedPath(segments);
if (0 == appendedPath.compareTo(QWinFrame.getQWinFrame().getUserProperties().getMostRecentAppendedPath())) {
DefaultMutableTreeNode directoryTreeNode = findContainingDirectoryTreeNode(serverName, projectName, viewName, appendedPath);
pendingDirectoryNode = directoryTreeNode;
}
}
}
}
ProjectTreeNode findProjectTreeNode(final String serverName, final String projectName) {
ProjectTreeNode foundProject = null;
ServerTreeNode serverNode = serverNodeMap.get(serverName);
Enumeration enumeration = serverNode.children();
while (enumeration.hasMoreElements()) {
ProjectTreeNode projectNode = (ProjectTreeNode) enumeration.nextElement();
AbstractProjectProperties projectProperties = projectNode.getProjectProperties();
if (projectProperties.getProjectName().equals(projectName)) {
foundProject = projectNode;
break;
}
}
return foundProject;
}
ViewTreeNode findProjectViewTreeNode(final String serverName, final String projectName, final String viewName) {
ViewTreeNode foundView = null;
ServerTreeNode serverNode = serverNodeMap.get(serverName);
Enumeration enumeration = serverNode.children();
while (enumeration.hasMoreElements()) {
ProjectTreeNode projectNode = (ProjectTreeNode) enumeration.nextElement();
AbstractProjectProperties projectProperties = projectNode.getProjectProperties();
if (projectProperties.getProjectName().equals(projectName)) {
Enumeration viewEnumeration = projectNode.children();
while (viewEnumeration.hasMoreElements()) {
ViewTreeNode viewTreeNode = (ViewTreeNode) viewEnumeration.nextElement();
if (viewTreeNode.getViewName().equals(viewName)) {
foundView = viewTreeNode;
break;
}
}
break;
}
}
return foundView;
}
/**
* Find the tree node given the server, project, view, and appended path.
* @param serverName the server name.
* @param projectName the project name.
* @param viewName the view name.
* @param appendedPath the appended path.
* @return the tree node for the given parameters. This will return null if the node cannot be found.
*/
public DefaultMutableTreeNode findContainingDirectoryTreeNode(final String serverName, final String projectName, final String viewName, final String appendedPath) {
ViewTreeNode foundView;
DefaultMutableTreeNode foundDirectory = null;
ServerTreeNode serverNode = serverNodeMap.get(serverName);
Enumeration enumeration = serverNode.children();
while (enumeration.hasMoreElements()) {
ProjectTreeNode projectNode = (ProjectTreeNode) enumeration.nextElement();
AbstractProjectProperties projectProperties = projectNode.getProjectProperties();
if (projectProperties.getProjectName().equals(projectName)) {
Enumeration viewEnumeration = projectNode.children();
while (viewEnumeration.hasMoreElements()) {
ViewTreeNode viewTreeNode = (ViewTreeNode) viewEnumeration.nextElement();
if (viewTreeNode.getViewName().equals(viewName)) {
foundView = viewTreeNode;
if (appendedPath.length() == 0) {
foundDirectory = foundView;
} else {
Enumeration directoryEnumeration = foundView.depthFirstEnumeration();
while (directoryEnumeration.hasMoreElements()) {
DefaultMutableTreeNode currentNode = (DefaultMutableTreeNode) directoryEnumeration.nextElement();
if (currentNode instanceof DirectoryTreeNode) {
DirectoryTreeNode directoryTreeNode = (DirectoryTreeNode) currentNode;
if (appendedPath.compareToIgnoreCase(directoryTreeNode.getAppendedPath()) == 0) {
foundDirectory = currentNode;
break;
}
}
}
}
break;
}
}
break;
}
}
return foundDirectory;
}
private DefaultMutableTreeNode findDeepestParent(final String serverName, final String projectName, final String viewName, final String appendedPath) {
ViewTreeNode foundView;
DefaultMutableTreeNode foundDirectory = null;
String deepestAppendedPath = "";
ServerTreeNode serverNode = serverNodeMap.get(serverName);
Enumeration enumeration = serverNode.children();
while (enumeration.hasMoreElements()) {
ProjectTreeNode projectNode = (ProjectTreeNode) enumeration.nextElement();
AbstractProjectProperties projectProperties = projectNode.getProjectProperties();
if (projectProperties.getProjectName().equals(projectName)) {
Enumeration viewEnumeration = projectNode.children();
while (viewEnumeration.hasMoreElements()) {
ViewTreeNode viewTreeNode = (ViewTreeNode) viewEnumeration.nextElement();
if (viewTreeNode.getViewName().equals(viewName)) {
foundView = viewTreeNode;
if (appendedPath.length() == 0) {
foundDirectory = foundView;
} else {
Enumeration directoryEnumeration = foundView.depthFirstEnumeration();
while (directoryEnumeration.hasMoreElements()) {
DefaultMutableTreeNode currentNode = (DefaultMutableTreeNode) directoryEnumeration.nextElement();
if (currentNode instanceof DirectoryTreeNode) {
DirectoryTreeNode directoryTreeNode = (DirectoryTreeNode) currentNode;
String directoryTreeNodeAppendedPath = directoryTreeNode.getAppendedPath();
if (appendedPath.startsWith(directoryTreeNodeAppendedPath)) {
if (directoryTreeNode.getAppendedPath().length() > deepestAppendedPath.length()) {
foundDirectory = directoryTreeNode;
deepestAppendedPath = directoryTreeNode.getAppendedPath();
}
}
}
}
}
break;
}
}
break;
}
}
return foundDirectory;
}
private void addSubprojectNode(ViewTreeNode viewTreeNode, AbstractProjectProperties projectProperties, String[] segments) {
// We need to find the parent for this node.
synchronized (ProjectTreeModel.class) {
if (deepestParent == null) {
final String serverName = QWinFrame.getQWinFrame().getServerName();
deepestParent = findDeepestParent(serverName, viewTreeNode.getProjectName(), viewTreeNode.getViewName(), buildAppendedPath(segments));
}
}
DefaultMutableTreeNode node = viewTreeNode;
for (int i = 0; i < segments.length; i++) {
node = getNode(viewTreeNode, node, projectProperties, segments, i);
}
}
private String buildAppendedPath(String[] segments) {
StringBuilder stringBuffer = new StringBuilder();
for (int i = 0; i < segments.length; i++) {
stringBuffer.append(segments[i]);
if (i + 1 < segments.length) {
stringBuffer.append(QVCSConstants.QVCS_STANDARD_PATH_SEPARATOR_STRING);
}
}
return stringBuffer.toString();
}
private void deleteSubprojectNode(ViewTreeNode viewTreeNode, AbstractProjectProperties projectProperties, String[] segments) {
// Find the node to delete...
DefaultMutableTreeNode node = viewTreeNode;
for (int i = 0; i < segments.length; i++) {
node = getNode(viewTreeNode, node, projectProperties, segments, i);
}
DefaultMutableTreeNode nodeToDelete = node;
DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) nodeToDelete.getParent();
parentNode.remove(nodeToDelete);
scheduleUpdate(parentNode);
}
private DefaultMutableTreeNode getNode(ViewTreeNode viewTreeNode, DefaultMutableTreeNode node, AbstractProjectProperties projectProperties, String[] segments, int index) {
DirectoryTreeNode foundNode = null;
boolean foundNodeFlag = false;
String segment = segments[index];
Enumeration enumeration = node.children();
while (enumeration.hasMoreElements()) {
DirectoryTreeNode candidate = (DirectoryTreeNode) enumeration.nextElement();
if (0 == candidate.toString().compareTo(segment)) {
foundNode = candidate;
foundNodeFlag = true;
}
}
// The segment doesn't exist yet. We'll need to create it.
if (!foundNodeFlag) {
// Figure out the appendedPath.
StringBuilder appendedPath = new StringBuilder();
for (int i = 0; i <= index; i++) {
appendedPath.append(segments[i]);
if (i <= index - 1) {
appendedPath.append(File.separator);
}
}
DirectoryTreeNode child = new DirectoryTreeNode(viewTreeNode.getViewName(), appendedPath.toString(), projectProperties);
foundNode = child;
node.add(child);
scheduleUpdate(viewTreeNode);
}
return foundNode;
}
private void scheduleUpdate(DefaultMutableTreeNode node) {
// Cancel pending notify task.
if (notifyTask != null) {
if (notifyTask.cancel()) {
QWinUtility.logProblem(Level.FINE, "Cancelled node structure changed tree model");
}
this.notifyTask = null;
}
final DefaultMutableTreeNode finalDefaultMutableTreeNode = node;
TimerTask newNotifyTask = new TimerTask() {
@Override
public void run() {
// Run this on the swing thread.
Runnable swingTask = new Runnable() {
@Override
public void run() {
synchronized (ProjectTreeModel.class) {
if (pendingDirectoryNode != null) {
ProjectTreeControl.getInstance().selectNode(pendingDirectoryNode);
pendingDirectoryNode = null;
} else if (deepestParent != null) {
projectTreeModel.nodeStructureChanged(deepestParent);
} else {
projectTreeModel.nodeStructureChanged(finalDefaultMutableTreeNode);
}
deepestParent = null;
}
}
};
SwingUtilities.invokeLater(swingTask);
}
};
Date now = new Date();
Date whenToRun = new Date(now.getTime() + UPDATE_DELAY);
timerDaemon.schedule(newNotifyTask, whenToRun);
this.notifyTask = newNotifyTask;
}
private void loadModel() {
// Where all the property files can be found...
File propertiesDirectory = new java.io.File(System.getProperty("user.dir")
+ System.getProperty("file.separator")
+ QVCSConstants.QVCS_PROPERTIES_DIRECTORY);
// Create the root node for the tree
DefaultServerTreeNode rootNode = new DefaultServerTreeNode(DefaultServerProperties.getInstance());
// Create the tree model
projectTreeModel = new javax.swing.tree.DefaultTreeModel(rootNode, false);
// Load the server nodes.
loadServerNodes(rootNode, propertiesDirectory);
if (QWinFrame.getQWinFrame().getUserProperties().getBypassLoginDialogFlag()) {
String serverName = QWinFrame.getQWinFrame().getUserProperties().getBypassServerName();
if ((serverName != null) && (serverName.length() > 0)) {
final ServerTreeNode serverNode = serverNodeMap.get(serverName);
if (serverNode != null) {
Runnable later = new Runnable() {
@Override
public void run() {
ProjectTreeControl.getInstance().selectNode(serverNode);
}
};
SwingUtilities.invokeLater(later);
}
}
}
}
private void loadServerNodes(DefaultServerTreeNode rootNode, File projectsDirectory) {
QVCSServerNamesFilter serverNameFilter = new QVCSServerNamesFilter();
java.io.File[] serverFiles = projectsDirectory.listFiles(serverNameFilter);
if (serverFiles != null) {
for (File serverFile : serverFiles) {
String serverName = serverNameFilter.getServerName(serverFile.getName());
try {
ServerProperties serverProperties = new ServerProperties(serverName);
ServerTreeNode serverNode = new ServerTreeNode(serverProperties);
rootNode.add(serverNode);
serverNodeMap.put(serverName, serverNode);
} catch (NullPointerException | ClassCastException e) {
QWinUtility.logProblem(Level.WARNING, "Failed to load project " + serverName + " into tree model." + Utility.expandStackTraceToString(e));
}
}
}
}
/**
* Reload the server nodes from the property files.
*/
public void reloadServerNodes() {
// Make sure these are empty.
serverNodeMap.clear();
projectNodeMap.clear();
// Where all the property files can be found...
File projectsDirectory = new java.io.File(System.getProperty("user.dir")
+ System.getProperty("file.separator")
+ QVCSConstants.QVCS_PROPERTIES_DIRECTORY);
QVCSServerNamesFilter serverNameFilter = new QVCSServerNamesFilter();
java.io.File[] serverFiles = projectsDirectory.listFiles(serverNameFilter);
DefaultServerTreeNode rootNode = (DefaultServerTreeNode) getTreeModel().getRoot();
Map<String, ServerProperties> newServers = new TreeMap<>();
Map<String, ServerProperties> oldServers = new TreeMap<>();
Map<String, ServerTreeNode> oldServerNodes = new TreeMap<>();
for (File serverFile : serverFiles) {
String serverName = serverNameFilter.getServerName(serverFile.getName());
try {
ServerProperties serverProperties = new ServerProperties(serverName);
newServers.put(serverName, serverProperties);
} catch (Exception e) {
QWinUtility.logProblem(Level.WARNING, "Failed to load project " + serverName + " into tree model.");
}
}
// Find the old servers...
for (int i = 0; i < rootNode.getChildCount(); i++) {
ServerTreeNode serverNode = (ServerTreeNode) rootNode.getChildAt(i);
ServerProperties serverProperties = serverNode.getServerProperties();
String serverName = serverProperties.getServerName();
oldServers.put(serverName, serverProperties);
oldServerNodes.put(serverName, serverNode);
}
for (ServerProperties newServerProperties : newServers.values()) {
String serverName = newServerProperties.getServerName();
ServerProperties oldServerProperties = oldServers.get(serverName);
if (oldServerProperties != null) {
// There is an existing server with this name. Update the properties
ServerTreeNode oldServerTreeNode = oldServerNodes.get(serverName);
rootNode.remove(oldServerTreeNode);
ServerTreeNode newServerNode = new ServerTreeNode(newServerProperties);
rootNode.add(newServerNode);
serverNodeMap.put(serverName, newServerNode);
} else {
// This one does not exist in the current list. We'll need to add
// it.
ServerTreeNode serverNode = new ServerTreeNode(newServerProperties);
rootNode.add(serverNode);
serverNodeMap.put(serverName, serverNode);
}
}
for (ServerProperties oldServerProperties : oldServers.values()) {
String serverName = oldServerProperties.getServerName();
ServerProperties serverProperties = newServers.get(serverName);
if (serverProperties == null) {
// This one does not exist in the new list. We'll need to delete
// it.
ServerTreeNode serverNode = oldServerNodes.get(serverName);
rootNode.remove(serverNode);
}
}
// We need to close all transports since the server tree will get reset, and we'll lose all of our tree nodes.
TransportProxyFactory.getInstance().closeAllTransports();
projectTreeModel.nodeStructureChanged(rootNode);
}
TreeNode loadRemoteProjects(ServerResponseListProjects response) {
TreeNode treeNode = null;
projectNodeMap.clear();
try {
String[] projectList = response.getProjectList();
Properties[] propertiesList = response.getPropertiesList();
// Find the server for this project, and add it as a child of the
// server's node.
String serverName = response.getServerName();
ServerTreeNode serverNode = serverNodeMap.get(serverName);
if (serverNode != null) {
// We'll replace any existing children with the list we just
// received.
serverNode.removeAllChildren();
// Add all the projects that we received.
for (int i = 0; i < response.getProjectList().length; i++) {
RemoteProjectProperties projectProperties = new RemoteProjectProperties(projectList[i], propertiesList[i]);
ProjectTreeNode projectNode = new ProjectTreeNode(projectProperties);
// Add this as a child of the server's node.
serverNode.add(projectNode);
treeNode = serverNode;
// And hang on to this for easy reference.
projectNodeMap.put(getProjectNodeKey(serverName, projectList[i]), projectNode);
}
} else {
QWinUtility.logProblem(Level.WARNING, "received project list from unknown server: " + serverName);
}
} catch (Exception e) {
QWinUtility.logProblem(Level.WARNING, "Failed to load projects for server: " + response.getServerName());
}
return treeNode;
}
TreeNode loadRemoteViews(ServerResponseListViews response) {
TreeNode treeNode = null;
try {
String[] viewList = response.getViewList();
Properties[] viewPropertiesList = response.getViewProperties();
// Find the server for this project, and add it as a child of the
// server's node.
String serverName = response.getServerName();
ServerTreeNode serverNode = serverNodeMap.get(serverName);
if (serverNode != null) {
// Find the project node...
ProjectTreeNode projectNode = projectNodeMap.get(getProjectNodeKey(serverName, response.getProjectName()));
if (projectNode != null) {
// We'll replace any existing children with the list we just
// received.
projectNode.removeAllChildren();
// Add all the projects that we received.
for (int i = 0; i < response.getViewList().length; i++) {
RemoteViewProperties viewProperties = new RemoteViewProperties(response.getProjectName(), viewList[i], viewPropertiesList[i]);
ViewTreeNode viewNode;
if (viewProperties.getIsReadOnlyViewFlag()) {
viewNode = new ReadOnlyViewNode(viewProperties, viewList[i]);
} else {
viewNode = new ReadWriteViewNode(viewProperties, viewList[i]);
}
// Add this as a child of the project's node.
projectNode.add(viewNode);
}
treeNode = projectNode;
}
} else {
QWinUtility.logProblem(Level.WARNING, "received project list from unknown server: " + serverName);
}
} catch (Exception e) {
QWinUtility.logProblem(Level.WARNING, "Failed to load projects for server: " + response.getServerName());
}
return treeNode;
}
private String getProjectNodeKey(final String serverName, final String projectName) {
return serverName + ":" + projectName;
}
/**
* Search within the given project for the given directory. Return the treepath for the given node. If the node is not found, return a treepath to the root node.
*/
TreePath getPath(String serverName, String projectName, String appendedPath, String projectType) {
DefaultMutableTreeNode node = null;
ServerTreeNode serverNode = serverNodeMap.get(serverName);
Enumeration enumerator = serverNode.preorderEnumeration();
while (enumerator.hasMoreElements()) {
DefaultMutableTreeNode currentNode = (DefaultMutableTreeNode) enumerator.nextElement();
if (currentNode instanceof ProjectTreeNode) {
if (appendedPath.length() == 0) {
ProjectTreeNode projectNode = (ProjectTreeNode) currentNode;
AbstractProjectProperties activeProject = projectNode.getProjectProperties();
if (0 == projectName.compareTo(activeProject.getProjectName())) {
if (activeProject.isRemoteProject() && (0 == projectType.compareTo(QVCSConstants.QVCS_REMOTE_PROJECT_TYPE))) {
node = currentNode;
break;
}
}
}
} else if (currentNode instanceof DirectoryTreeNode) {
DirectoryTreeNode directoryTreeNode = (DirectoryTreeNode) currentNode;
if (appendedPath.compareToIgnoreCase(directoryTreeNode.getAppendedPath()) == 0) {
AbstractProjectProperties projectProperties = directoryTreeNode.getProjectProperties();
if (projectProperties.getProjectName().equals(projectName)) {
node = currentNode;
break;
}
}
}
}
if (node != null) {
return new TreePath(node.getPath());
} else {
// We couldn't find the node. We'll use the root instead.
return new TreePath(projectTreeModel.getRoot());
}
}
/**
* Return an alphabetical list of projects that we know about.
* @return an alphabetical list of projects that we know about.
*/
public final synchronized List<String> getProjectNames() {
List<String> projectList = Collections.synchronizedList(new ArrayList<String>());
DefaultServerTreeNode rootNode = (DefaultServerTreeNode) getTreeModel().getRoot();
Enumeration enumerator = rootNode.preorderEnumeration();
while (enumerator.hasMoreElements()) {
DefaultMutableTreeNode currentNode = (DefaultMutableTreeNode) enumerator.nextElement();
if (currentNode instanceof ProjectTreeNode) {
ProjectTreeNode projectNode = (ProjectTreeNode) currentNode;
projectList.add(projectNode.getProjectName());
}
}
Collections.sort(projectList);
return projectList;
}
synchronized DefaultMutableTreeNode findNode(TreePath treePath) {
DefaultMutableTreeNode foundNode = null;
DefaultMutableTreeNode rootNode = (DefaultMutableTreeNode) projectTreeModel.getRoot();
Enumeration enumeration = rootNode.depthFirstEnumeration();
while (enumeration.hasMoreElements()) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) enumeration.nextElement();
TreePath nodePath = new TreePath(node.getPath());
if (0 == nodePath.toString().compareTo(treePath.toString())) {
foundNode = node;
break;
}
}
return foundNode;
}
/**
* Get a map of peer views.
*
* @param serverName the server name.
* @param projectName the project name.
* @param viewName the view name.
* @return a map of view nodes that are peers to the given view.
*/
public final synchronized Map<String, ViewTreeNode> getPeerViews(final String serverName, final String projectName,
final String viewName) {
Map<String, ViewTreeNode> viewList = Collections.synchronizedMap(new TreeMap<String, ViewTreeNode>());
ProjectTreeNode projectNode = findProjectTreeNode(serverName, projectName);
Enumeration enumerator = projectNode.preorderEnumeration();
while (enumerator.hasMoreElements()) {
DefaultMutableTreeNode currentNode = (DefaultMutableTreeNode) enumerator.nextElement();
if (currentNode instanceof ViewTreeNode) {
ViewTreeNode viewNode = (ViewTreeNode) currentNode;
if (viewNode.getViewName().equals(viewName)) {
continue;
}
viewList.put(viewNode.getViewName(), viewNode);
}
}
return viewList;
}
}