/*******************************************************************************
* Mission Control Technologies, Copyright (c) 2009-2012, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* The MCT platform is 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.
*
* MCT includes source code licensed under additional open source licenses. See
* the MCT Open Source Licenses file included with this distribution or the About
* MCT Licenses dialog available at runtime from the MCT Help menu for additional
* information.
*******************************************************************************/
package gov.nasa.arc.mct.gui.actions;
import gov.nasa.arc.mct.components.AbstractComponent;
import gov.nasa.arc.mct.gui.ActionContext;
import gov.nasa.arc.mct.gui.ContextAwareAction;
import gov.nasa.arc.mct.gui.MCTMutableTreeNode;
import gov.nasa.arc.mct.gui.OptionBox;
import gov.nasa.arc.mct.gui.View;
import gov.nasa.arc.mct.gui.housing.MCTDirectoryArea;
import gov.nasa.arc.mct.gui.housing.MCTHousing;
import gov.nasa.arc.mct.gui.impl.ActionContextImpl;
import gov.nasa.arc.mct.platform.spi.PlatformAccess;
import gov.nasa.arc.mct.policy.PolicyContext;
import gov.nasa.arc.mct.policy.PolicyInfo;
import gov.nasa.arc.mct.policymgr.PolicyManagerImpl;
import gov.nasa.arc.mct.services.component.ViewInfo;
import gov.nasa.arc.mct.services.component.ViewType;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Set;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTree;
import javax.swing.SwingConstants;
import javax.swing.tree.TreePath;
/**
* This action removes a manifestation in the directory area. Note that
* removing a manifestation under "created by me" is not allowed, but
* it not part of the composition policy category.
* @author nija.shi@nasa.gov
*/
@SuppressWarnings("serial")
public class RemoveManifestationAction extends ContextAwareAction {
private static final ResourceBundle bundle = ResourceBundle.getBundle("gov/nasa/arc/mct/gui/actions/Bundle");
private static String TEXT = "Remove Manifestation";
private static String WARNING = bundle.getString("RemoveLastManifestationWarningTitle");
private TreePath[] selectedTreePaths;
private ActionContextImpl actionContext;
public RemoveManifestationAction() {
super(TEXT);
}
@Override
public boolean canHandle(ActionContext context) {
actionContext = (ActionContextImpl) context;
MCTHousing activeHousing = actionContext.getTargetHousing();
if (activeHousing == null)
return false;
Collection<View> selection =
activeHousing.getSelectionProvider().getSelectedManifestations();
if (selection.isEmpty())
return false;
ViewInfo vi = selection.iterator().next().getInfo();
if (selection.isEmpty() ||
!(vi != null && vi.getViewType() == ViewType.NODE)){
return false;
}
if (!(activeHousing.getDirectoryArea() instanceof MCTDirectoryArea)) {
return false;
}
MCTDirectoryArea directory = MCTDirectoryArea.class.cast(activeHousing.getDirectoryArea());
MCTMutableTreeNode firstSelectedNode = directory.getSelectedDirectoryNode();
if (firstSelectedNode == null)
return false;
JTree tree = firstSelectedNode.getParentTree();
selectedTreePaths = tree.getSelectionPaths();
return selectedTreePaths != null && selectedTreePaths.length > 0;
}
@Override
public boolean isEnabled() {
for (TreePath path : selectedTreePaths) {
if (!isRemovable(path))
return false;
}
return true;
}
@Override
public void actionPerformed(ActionEvent e) {
Map<String,Integer> numberOfParents = new HashMap<String,Integer>();
Set<String> lastManifestationComponents = new HashSet<String>();
List<Map<MCTMutableTreeNode, MCTMutableTreeNode>> okToRemoveManifestations = new ArrayList<Map<MCTMutableTreeNode, MCTMutableTreeNode>>();
for (TreePath path : selectedTreePaths) {
MCTMutableTreeNode selectedNode = (MCTMutableTreeNode) path.getLastPathComponent();
MCTMutableTreeNode parentNode = (MCTMutableTreeNode) selectedNode.getParent();
AbstractComponent selectedComponent = ((View) selectedNode.getUserObject()).getManifestedComponent();
if (!numberOfParents.containsKey(selectedComponent.getComponentId())) {
numberOfParents.put(selectedComponent.getComponentId(), Integer.valueOf(selectedComponent.getReferencingComponents().size()));
}
// If component is the last manifestation,
if (numberOfParents.get(selectedComponent.getComponentId()) == 1) {
PolicyContext policyContext = new PolicyContext();
policyContext.setProperty(PolicyContext.PropertyName.TARGET_COMPONENT.getName(), selectedComponent);
policyContext.setProperty(PolicyContext.PropertyName.ACTION.getName(), 'w');
String deleteKey = PolicyInfo.CategoryType.CAN_DELETE_COMPONENT_POLICY_CATEGORY.getKey();
Object[] messages = new Object[2];
JLabel label1 = new JLabel("Cannot remove");
label1.setFont(label1.getFont().deriveFont(Font.BOLD));
messages[0] = label1;
messages[1] = bundle.getString("NotOwnerOfManifestation");
if (!PolicyManagerImpl.getInstance().execute(deleteKey, policyContext).getStatus()) {
OptionBox.showMessageDialog(actionContext.getWindowManifestation(),
messages,
"ERROR: "+ WARNING,
OptionBox.ERROR_MESSAGE);
return;
}
// If component has no children,
if (selectedComponent.getComponents().size() == 0) {
lastManifestationComponents.add(selectedComponent.getComponentId());
//Remove it from ok-to-remove Manifestations
Iterator<Map<MCTMutableTreeNode, MCTMutableTreeNode>> iterator = okToRemoveManifestations.iterator();
while (iterator.hasNext()) {
Map<MCTMutableTreeNode, MCTMutableTreeNode> map = iterator.next();
for (MCTMutableTreeNode mapNode : map.values()) {
if (((View) mapNode.getUserObject()).getManifestedComponent().getComponentId().equals(selectedComponent.getComponentId())) {
iterator.remove();
}
}
}
} else {
//At least one component has children
handleWarnings(false, okToRemoveManifestations, lastManifestationComponents);
return;
}
} else {
// Has more than 1 parent
Map<MCTMutableTreeNode, MCTMutableTreeNode> okManifestationMap = new HashMap<MCTMutableTreeNode, MCTMutableTreeNode>();
okManifestationMap.put(parentNode, selectedNode);
okToRemoveManifestations.add(okManifestationMap);
numberOfParents.put(selectedComponent.getComponentId(), numberOfParents.get(selectedComponent.getComponentId())-1);
}
}
if (okToRemoveManifestations.size() + lastManifestationComponents.size() > 0) {
handleWarnings(true, okToRemoveManifestations, lastManifestationComponents);
}
}
private void handleWarnings(boolean canRemove, List<Map<MCTMutableTreeNode, MCTMutableTreeNode>> okToRemoveManifestations,
Set<String> lastManifestationComponents) {
if (!canRemove) {
OptionBox.showMessageDialog(actionContext.getWindowManifestation(),
bundle.getString("RemoveLastManifestationHasDescendantsErrorText"),
"ERROR: "+ WARNING,
OptionBox.ERROR_MESSAGE);
return;
} else {
if (lastManifestationComponents.size() > 0) {
Object[] options = { "OK" , "Cancel" };
int choice = OptionBox.showOptionDialog(actionContext.getWindowManifestation(),
buildWarningPanel(okToRemoveManifestations, lastManifestationComponents),
WARNING,
OptionBox.YES_NO_OPTION,
OptionBox.WARNING_MESSAGE,
null,
options,
null);
if (choice != 0) {
return;
}
}
}
// Remove and/or Delete Objects
for (Map<MCTMutableTreeNode, MCTMutableTreeNode> okMap : okToRemoveManifestations) {
AbstractComponent parentComponent = ((View) okMap.entrySet().iterator().next().getKey().getUserObject()).getManifestedComponent();
AbstractComponent selectedComponent = ((View) okMap.entrySet().iterator().next().getValue().getUserObject()).getManifestedComponent();
parentComponent.removeDelegateComponent(selectedComponent);
parentComponent.save();
}
for (String selectedComponentId : lastManifestationComponents) {
PlatformAccess.getPlatform().getPersistenceProvider().delete(Collections.singleton(AbstractComponent.getComponentById(selectedComponentId)));
PlatformAccess.getPlatform().getWindowManager().closeWindows(selectedComponentId);
}
}
private JPanel buildWarningPanel(List<Map<MCTMutableTreeNode, MCTMutableTreeNode>> okToRemoveManifestations,
Set<String> lastManifestationComponents) {
Set<String> okComps = new HashSet<String>(okToRemoveManifestations.size());
List<String> lastComps = new ArrayList<String>(lastManifestationComponents.size());
for (Map<MCTMutableTreeNode, MCTMutableTreeNode> okMap : okToRemoveManifestations) {
AbstractComponent selectedComponent = ((View) okMap.entrySet().iterator().next().getValue().getUserObject()).getManifestedComponent();
okComps.add(selectedComponent.getDisplayName());
}
for (String comp : lastManifestationComponents) {
lastComps.add(AbstractComponent.getComponentById(comp).getDisplayName());
}
JPanel warning = new JPanel(new GridLayout(3,2, 0, 0));
warning.setPreferredSize(new Dimension(600,220));
@SuppressWarnings({ "rawtypes", "unchecked" }) // Java 7 compatibility
JList okList = new JList(okComps.toArray());
@SuppressWarnings({ "rawtypes", "unchecked" }) // Java 7 compatibility
JList lastManifestationList = new JList(lastComps.toArray());
JScrollPane scrollPane1 = new JScrollPane(okList);
scrollPane1.setPreferredSize(new Dimension(180,100));
JScrollPane scrollPane2 = new JScrollPane(lastManifestationList);
scrollPane2.setPreferredSize(new Dimension(180,100));
JLabel okLabel = new JLabel(bundle.getString("SafeToRemoveManifestation"));
okLabel.setPreferredSize(new Dimension(200,20));
okLabel.setVerticalAlignment(SwingConstants.BOTTOM);
JLabel lastManifestationLabel = new JLabel(bundle.getString("RemoveManifestationBecomesDelete"));
lastManifestationLabel.setPreferredSize(new Dimension(200,20));
lastManifestationLabel.setVerticalAlignment(SwingConstants.BOTTOM);
JTextArea warningMessage = new JTextArea(bundle.getString("RemoveLastManifestationWarningTextA"));
warningMessage.setWrapStyleWord(true);
warningMessage.setLineWrap(true);
warningMessage.setOpaque(false);
warningMessage.setPreferredSize(new Dimension(180,100));
warningMessage.setEditable(false);
JTextArea removeMessage = new JTextArea(bundle.getString("RemoveSafelyWarning"));
removeMessage.setWrapStyleWord(true);
removeMessage.setLineWrap(true);
removeMessage.setOpaque(false);
removeMessage.setPreferredSize(new Dimension(200,100));
removeMessage.setMargin(new Insets(0,10,0,10));
removeMessage.setEditable(false);
warning.add(removeMessage);
warning.add(warningMessage);
warning.add(okLabel);
warning.add(lastManifestationLabel);
warning.add(scrollPane1);
warning.add(scrollPane2);
return warning;
}
private boolean isRemovable(TreePath path) {
MCTMutableTreeNode lastPathComponent = (MCTMutableTreeNode) path.getLastPathComponent();
MCTMutableTreeNode parentNode = (MCTMutableTreeNode) lastPathComponent.getParent();
if (parentNode == null)
return false;
AbstractComponent parentComponent = ((View) parentNode.getUserObject()).getManifestedComponent();
AbstractComponent selectedComponent = View.class.cast(lastPathComponent.getUserObject()).getManifestedComponent();
PolicyContext context = new PolicyContext();
context.setProperty(PolicyContext.PropertyName.TARGET_COMPONENT.getName(), parentComponent);
context.setProperty(PolicyContext.PropertyName.ACTION.getName(), 'w');
context.setProperty(PolicyContext.PropertyName.SOURCE_COMPONENTS.getName(), Collections.singleton(selectedComponent));
context.setProperty(PolicyContext.PropertyName.VIEW_MANIFESTATION_PROVIDER.getName(), parentNode.getUserObject());
String canRemoveManifestationKey = PolicyInfo.CategoryType.CAN_REMOVE_MANIFESTATION_CATEGORY.getKey();
boolean canRemoveManifestation = PolicyManagerImpl.getInstance().execute(canRemoveManifestationKey, context).getStatus();
if (canRemoveManifestation) {
String compositionKey = PolicyInfo.CategoryType.COMPOSITION_POLICY_CATEGORY.getKey();
return PolicyManagerImpl.getInstance().execute(compositionKey, context).getStatus();
}
return canRemoveManifestation;
}
}