/******************************************************************************** * * * (c) Copyright 2010 Verizon Communications USA and The Open University UK * * * * This software is freely distributed in accordance with * * the GNU Lesser General Public (LGPL) license, version 3 or later * * as published by the Free Software Foundation. * * For details see LGPL: http://www.fsf.org/licensing/licenses/lgpl.html * * and GPL: http://www.fsf.org/licensing/licenses/gpl-3.0.html * * * * This software is provided by the copyright holders and contributors "as is" * * and any express or implied warranties, including, but not limited to, the * * implied warranties of merchantability and fitness for a particular purpose * * are disclaimed. In no event shall the copyright owner or contributors be * * liable for any direct, indirect, incidental, special, exemplary, or * * consequential damages (including, but not limited to, procurement of * * substitute goods or services; loss of use, data, or profits; or business * * interruption) however caused and on any theory of liability, whether in * * contract, strict liability, or tort (including negligence or otherwise) * * arising in any way out of the use of this software, even if advised of the * * possibility of such damage. * * * ********************************************************************************/ package com.compendium.ui.edits; import java.sql.SQLException; import java.util.Hashtable; import java.util.Vector; import javax.swing.undo.AbstractUndoableEdit; import javax.swing.undo.CannotRedoException; import javax.swing.undo.CannotUndoException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.compendium.ProjectCompendium; import com.compendium.core.ICoreConstants; import com.compendium.core.datamodel.IModel; import com.compendium.core.datamodel.Link; import com.compendium.core.datamodel.LinkProperties; import com.compendium.core.datamodel.NodePosition; import com.compendium.core.datamodel.NodeSummary; import com.compendium.core.datamodel.PCSession; import com.compendium.core.datamodel.View; import com.compendium.ui.UILink; import com.compendium.ui.UIList; import com.compendium.ui.UIListViewFrame; import com.compendium.ui.UIMapViewFrame; import com.compendium.ui.UINode; import com.compendium.ui.UIViewFrame; import com.compendium.ui.UIViewPane; import com.compendium.ui.plaf.LinkUI; import com.compendium.ui.plaf.ViewPaneUI; /** * The Abstract class for undo/redo edits (paste, cut, delete operations) * * @author Beatrix Zimmermann / Michelle Bachler */ public abstract class PCEdit extends AbstractUndoableEdit { static final Logger log = LoggerFactory.getLogger(PCEdit.class); /** Used while process to check VIews processed.*/ private Hashtable ht_checkViews = new Hashtable(51); /** A list of the UINode/NodePosition objects for this edit.*/ public Vector vtUndoNodes = new Vector(101); /** a List of the UILink object for this edit.*/ public Vector vtUndoLinks = new Vector(101); /** Helper Vector when undoing and edit.*/ private Vector undoNodeIndexes = new Vector(); /** The view frame for the view being edited.*/ public UIViewFrame oViewFrame = null; /** If a map view is being edited, the UIViewPane for the map.*/ public UIViewPane oViewPane; /** * Constructor. * @param viewFrame com.compendium.ui.UIViewFrame, the frame of the View being editied. */ public PCEdit (UIViewFrame viewFrame) { oViewFrame = viewFrame; if (oViewFrame instanceof UIListViewFrame) { } else { oViewPane = ((UIMapViewFrame)viewFrame).getViewPane(); } } /** * Add a <code>UINode</code> object to the list of nodes for this edit. * @param uinode com.compendium.ui.UINode, the node to add. */ public void AddNodeToEdit (UINode uinode) { if(!vtUndoNodes.contains(uinode)){ vtUndoNodes.addElement(uinode); } } /** * Add a <code>NodePosition</code> object to the list of nodes, and the the undoNodeIndexes Vector. * @param uinode com.compendium.core.datamodel.NodePosition, the <code>NodePosition</code> object to add. * @param index, the index to set when adding the node to the undoNodeIndexes Vector. */ public void AddNodeToEdit (NodePosition node, int index) { if(!vtUndoNodes.contains(node)){ vtUndoNodes.addElement(node); undoNodeIndexes.addElement(new Integer(index)); } } /** * Add a <code>UILink</code> object to the list of links for this edit. * @param uilink com.compendium.ui.UILink, the link to add. */ public void AddLinkToEdit (UILink uilink) { if(!vtUndoLinks.contains(uilink)){ vtUndoLinks.addElement(uilink); } } /** * Undoes the last edit operation of this type. * * @exception CannotRedoException if <code>canRedo</code> returns <code>false</code> * @see #canUndo */ public abstract void undo() throws CannotUndoException; /** * Redoes the previous edit of this type. * * @exception CannotRedoException if <code>canRedo</code> returns <code>false</code> * @see #canRedo */ public abstract void redo() throws CannotRedoException; /** * Returns true if this edit is <code>alive</code> * and <code>hasBeenDone</code> is <code>true</code>. * HERE: always return true. * * @return true if this edit is <code>alive</code> and <code>hasBeenDone</code> is <code>true</code> * * @see #undo * @see #redo */ public boolean canUndo() { return true; } /** * Returns <code>true</code> if this edit is <code>alive</code> * and <code>hasBeenDone</code> is <code>false</code>. * HERE: always return true. * * @return <code>true</code> if this edit is <code>alive</code> and <code>hasBeenDone</code> is <code>false</code> * * @see #undo * @see #redo */ public boolean canRedo() { return true; } /** * Abstract, should be overriden by subclasses to return the appropriate name. * * @return the presentation name for this edit. */ public abstract String getPresentationName(); /** * Process the undoing of a delete. */ public void unDeleteNodes() { ht_checkViews.clear(); View view = oViewFrame.getView(); Vector vtTempNodes = new Vector(); vtTempNodes = (Vector)vtUndoNodes.clone(); UIList uilist = ((UIListViewFrame)oViewFrame).getUIList(); IModel model = ProjectCompendium.APP.getModel(); PCSession session = model.getSession(); String sViewID = view.getId(); for(int i=0;i<vtTempNodes.size();i++) { NodePosition nodePos = (NodePosition)vtTempNodes.elementAt(i); String sNodeID = nodePos.getNode().getId(); boolean restored = false; try { restored = model.getNodeService().restoreNode(session, sNodeID); if (restored) { nodePos = model.getNodeService().restoreNodeView(session, sNodeID, sViewID); } } catch(SQLException ex) { log.info(ex.getMessage()); } view.addMemberNode(nodePos); if (nodePos.getNode() instanceof View) { View deletedView = (View)nodePos.getNode(); if (View.isListType(deletedView.getType())) { restoreDeletedNodes(deletedView); } else { restoreDeletedNodesAndLinks(deletedView); } } // DON'T ADD TWICE IN CASE ALREADY RESTORED FROM TRASHBIN if (uilist.getIndexOf(nodePos.getNode()) == -1) uilist.insertNode(nodePos, ((Integer)undoNodeIndexes.elementAt(i)).intValue()); } uilist.updateTable(); } /** * Restore deleted nodes and links. * @exception CannotUndoException. */ public void unDeleteNodesAndLinks() throws CannotUndoException { ht_checkViews.clear(); //get the active frame which will give the view to be searched ProjectCompendium.APP.setWaitCursor(); if (View.isListType(oViewFrame.getView().getType())) { unDeleteNodes(); ProjectCompendium.APP.setDefaultCursor(); return; } //restore all the nodes Vector vtTempNodes = new Vector(); vtTempNodes = (Vector)vtUndoNodes.clone(); IModel model = oViewPane.getView().getModel(); PCSession session = model.getSession(); String sViewID = oViewFrame.getView().getId(); UIViewPane viewpane = ((UIMapViewFrame)oViewFrame).getViewPane(); for(int i=0;i<vtTempNodes.size();i++) { boolean restored = false; UINode uinode = (UINode)vtTempNodes.elementAt(i); NodeSummary node = uinode.getNode(); NodePosition nodepos = uinode.getNodePosition(); node.initialize(model.getSession(),model); String sNodeID = node.getId(); try { restored = model.getNodeService().restoreNode(session, sNodeID); if (restored) { nodepos = model.getNodeService().restoreNodeView(session, sNodeID, sViewID); } // REPLACE ANY EXISITING INSTANCES I.E. GENERATED FROM A RESTORE // NEED TO IMPLEMENT THIS PROPERLY (once restored can not longer undo delete) UINode newUINode = (UINode)viewpane.get(sNodeID); if (newUINode != null) viewpane.removeObject(sNodeID); viewpane.getUI().addNode(uinode); oViewFrame.getView().addMemberNode(nodepos); if (uinode.getNode() instanceof View) { View deletedView = (View)uinode.getNode(); if (View.isListType(deletedView.getType())) restoreDeletedNodes(deletedView); else restoreDeletedNodesAndLinks(deletedView); } if(!restored) { log.info("Cannot restore" + node.getLabel() +" Node may have been purged from the DB"); //$NON-NLS-1$ //$NON-NLS-2$ } else { uinode.getUI().refreshBounds(); } } catch(SQLException ex) { ProjectCompendium.APP.displayError("Error: (PCEdit.unDeleteNodesAndLinks)\n\n" + ex.getLocalizedMessage()); //$NON-NLS-1$ } } // RESTORE ALL LINKS IF THIS VIEW IS A MAP if (View.isMapType(oViewFrame.getView().getType())) { Vector vtTempLinks = new Vector(); vtTempLinks = (Vector)vtUndoLinks.clone(); for(int i=0; i < vtTempLinks.size(); i++) { boolean restored = false; UILink uilink = (UILink)vtTempLinks.elementAt(i); // RESTORE THE LINK AND THE VIEWLINK try { String sLinkID = uilink.getLink().getId(); restored = model.getLinkService().restoreLink(session, sLinkID); restored = model.getViewService().restoreLink(session, sViewID, sLinkID); } catch(Exception ex) { ProjectCompendium.APP.displayError("Error: (PCEdit.unDeleteNodesAndLinks-2)\n\n" + ex.getLocalizedMessage()); //$NON-NLS-1$ } boolean wasSelected = uilink.isSelected(); if (restored) { Link link = uilink.getLink(); //add the link to the view if it isn't already in there UILink uiLinkInView = (UILink)oViewPane.get(link.getId()); if (uiLinkInView == null) { // RESTORE LINK TO VIEW AND ASSOCIATED NODES oViewFrame.getView().addMemberLink(uilink.getLinkProperties()); UILink newuilink = viewpane.getUI().addLink(uilink.getLinkProperties()); vtUndoLinks.removeElement(uilink); vtUndoLinks.addElement(newuilink); if (uilink.isSelected()) oViewPane.setSelectedLink(newuilink, ICoreConstants.MULTISELECT); } else { uilink = uiLinkInView; if (uiLinkInView.isSelected()) oViewPane.setSelectedLink(uilink, ICoreConstants.MULTISELECT); } } else { //create new one String id = oViewPane.getView().getModel().getUniqueID(); String type = uilink.getLink().getType(); UINode uifrom = uilink.getFromNode(); UINode uito = uilink.getToNode(); NodeSummary from = uilink.getFromNode().getNode(); NodeSummary to = uilink.getToNode().getNode(); int permission = ICoreConstants.WRITE; String sOriginalID = id; try { //add the link to the datamodel view LinkProperties linkProps = (LinkProperties)oViewPane.getView().addMemberLink(type, sOriginalID, ProjectCompendium.APP.getModel().getUserProfile().getUserName(), from, to, uilink.getText(), uilink.getLinkProperties()); linkProps.getLink().initialize(oViewPane.getView().getModel().getSession(), oViewPane.getView().getModel()); //create a link in UI layer - what about deleting the old object??? UILink newuilink = new UILink(linkProps.getLink(), linkProps, uifrom, uito); oViewPane.add(newuilink, (UIViewPane.LINK_LAYER)); newuilink.setBounds(uilink.getPreferredBounds()); uifrom.addLink(newuilink); uito.addLink(newuilink); newuilink.setSelected(uilink.isSelected()); if (newuilink.isSelected()) { oViewPane.removeLink(uilink); oViewPane.setSelectedLink(newuilink,ICoreConstants.MULTISELECT); } vtUndoLinks.removeElement(uilink); vtUndoLinks.addElement(newuilink); } catch(Exception ex) { log.info("Error: (PCEdit.unDeleteNodesAndLinks-3) "+ex.getMessage()); //$NON-NLS-1$ } } } } ProjectCompendium.APP.setDefaultCursor(); } /** * Re-Delete nodes. */ public void reDeleteNodes() { View parentView = oViewFrame.getView(); Vector vtTempNodes = new Vector(); vtTempNodes = (Vector)vtUndoNodes.clone(); for(int i=0;i<vtTempNodes.size();i++) { boolean deleted = false; try { NodePosition nodePos = (NodePosition)vtTempNodes.elementAt(i); deleted = parentView.removeMemberNode(nodePos.getNode()); ((UIListViewFrame)oViewFrame).getUIList().deleteNode(((Integer)undoNodeIndexes.elementAt(i)).intValue()); // IF NODE IS A VIEW AND IF NODE WAS ACTUALLY LAST INSTANCE AND WAS DELETED, DELETE CHILDREN if (nodePos.getNode() instanceof View && deleted) { View childView = (View)nodePos.getNode(); UIViewFrame childViewFrame = ProjectCompendium.APP.getViewFrame(childView, childView.getLabel()); if (childViewFrame instanceof UIMapViewFrame) ((UIMapViewFrame)childViewFrame).deleteChildren(childView); else ((UIListViewFrame)childViewFrame).deleteChildren(childView); } } catch(Exception ex) { log.info("Error (PCEdit.reDeleteNodes) \n\n"+ex.getMessage()); //$NON-NLS-1$ } } ((UIListViewFrame)oViewFrame).getUIList().updateTable(); } /** * ReDelete nodes and links. * @exception CannotUndoException. */ public void reDeleteNodesAndLinks() throws CannotRedoException { ProjectCompendium.APP.setWaitCursor(); if (View.isListType(oViewFrame.getView().getType())) { reDeleteNodes(); ProjectCompendium.APP.setDefaultCursor(); return; } //remove all the nodes again Vector vtTempNodes = new Vector(); vtTempNodes = (Vector)vtUndoNodes.clone(); //remove all the links again Vector vtTempLinks = new Vector(); vtTempLinks = (Vector)vtUndoLinks.clone(); for(int i=0;i<vtTempLinks.size();i++) { boolean restored = false; UILink uilink = (UILink)vtTempLinks.elementAt(i); LinkUI linkui = (LinkUI)uilink.getUI(); linkui.deleteLink(uilink); } //re-delete the nodes for(int i=0;i<vtTempNodes.size();i++) { boolean restored = false; UINode uinode = (UINode)vtTempNodes.elementAt(i); View parentView = oViewPane.getView(); boolean deleted = uinode.getUI().deleteNodeAndLinks(uinode, this); // IF NODE IS A VIEW AND IF NODE WAS ACTUALLY LAST INSTANCE AND WAS DELETED, DELETE CHILDREN if ((uinode.getNode() instanceof View) && deleted) { View childView = (View)uinode.getNode(); UIViewFrame childViewFrame = ProjectCompendium.APP.getViewFrame(childView, childView.getLabel()); if (childViewFrame instanceof UIMapViewFrame) ((UIMapViewFrame)childViewFrame).deleteChildren(childView); else ((UIListViewFrame)childViewFrame).deleteChildren(childView); } } ProjectCompendium.APP.setDefaultCursor(); } /** * Restore deleted nodes. * @param deletedView com.compendium.datamodel.View, the View to restore. * @exception CannotUndoException. */ public void restoreDeletedNodes(View deletedView) { try { Vector deletedNodes = deletedView.getDeletedNodes(); UIViewFrame deletedUIViewFrame = ProjectCompendium.APP.getViewFrame(deletedView, deletedView.getLabel()); UIList uilist = ((UIListViewFrame)deletedUIViewFrame).getUIList(); IModel model = oViewPane.getView().getModel(); PCSession session = model.getSession(); for (int i = 0; i < deletedNodes.size(); i++) { NodePosition np = (NodePosition)deletedNodes.elementAt(i); String sNodeID = np.getNode().getId(); String sViewID = deletedView.getId(); boolean restored = model.getNodeService().restoreNode(session, sNodeID); if (restored) { np = model.getNodeService().restoreNodeView(session, sNodeID, sViewID); } if (np != null) { deletedView.addMemberNode(np); if (np.getNode() instanceof View) { // DON'T RESTORE THE SAME VIEW TWICE if (!ht_checkViews.containsKey(sNodeID)) { ht_checkViews.put(sNodeID, np.getNode()); View view = (View)np.getNode(); if (View.isListType(view.getType())) { restoreDeletedNodes(view); } else { restoreDeletedNodesAndLinks(view); } } } // DON'T ADD THE SAME NODE TWICE TO THE SAME LIST if (uilist.getIndexOf(np.getNode()) == -1) { uilist.insertNode(np, np.getYPos()/10 - 1); } } } uilist.updateTable(); deletedNodes.removeAllElements(); } catch(Exception e) { ProjectCompendium.APP.displayError("Error: (PCEdit.restoreDeletedNodes)\n\n" + e.getLocalizedMessage()); //$NON-NLS-1$ } } /** * Restore deleted nodes and links. * @param deletedView com.compendium.datamodel.View, the view to restore. * @exception CannotUndoException. */ public void restoreDeletedNodesAndLinks(View deletedView) { try { IModel model = ProjectCompendium.APP.getModel(); PCSession session = model.getSession(); UIViewFrame deletedUIViewFrame = ProjectCompendium.APP.getViewFrame(deletedView, deletedView.getLabel()); String sViewID = deletedView.getId(); Vector deletedNodes = deletedView.getDeletedNodes(); ViewPaneUI deletedViewPaneUI = ((UIMapViewFrame)deletedUIViewFrame).getViewPane().getUI(); final int count = deletedNodes.size(); for (int i = 0; i < count; i++) { NodePosition np = (NodePosition)deletedNodes.elementAt(i); String sNodeID = np.getNode().getId(); boolean restored = model.getNodeService().restoreNode(session, sNodeID); if (restored) { np = model.getNodeService().restoreNodeView(session, sNodeID, sViewID); } if (np != null) { // REPLACE ANY EXISITING INSTANCES I.E. GENERATED FROM A RESTORE // NEED TO IMPLEMENT THIS PROPERLY (once restoerd can not longer undo delete) UINode newUINode = (UINode) ((UIMapViewFrame)deletedUIViewFrame).getViewPane().get(sNodeID); if (newUINode != null) ((UIMapViewFrame)deletedUIViewFrame).getViewPane().removeObject(sNodeID); deletedViewPaneUI.addNode(np); deletedView.addMemberNode(np); if (np.getNode() instanceof View) { // DON'T RESTORE THE SAME VIEW TWICE if (!ht_checkViews.containsKey(sNodeID)) { ht_checkViews.put(sNodeID, np.getNode()); View view = (View)np.getNode(); if (View.isListType(view.getType())) restoreDeletedNodes(view); else restoreDeletedNodesAndLinks(view); } } } } Vector deletedLinks = deletedView.getDeletedLinks(); for (int i = 0; i < deletedLinks.size(); i++) { LinkProperties linkProps = (LinkProperties)deletedLinks.elementAt(i); Link link = linkProps.getLink(); String sLinkID = link.getId(); // RESTORE THE LINK AND THE VIEWLINK boolean restored = model.getLinkService().restoreLink(session, sLinkID); restored = model.getViewService().restoreLink(session, sViewID, sLinkID); if (restored) { //add the link to the view if it isn't already in there UILink newuilink = (UILink)oViewPane.get(sLinkID); if (newuilink == null) { oViewFrame.getView().addMemberLink(linkProps); newuilink = deletedViewPaneUI.addLink(linkProps); } if (newuilink.isSelected()) { oViewPane.setSelectedLink(newuilink, ICoreConstants.MULTISELECT); } } else { //create new one String type = link.getType(); UINode uifrom = deletedViewPaneUI.getUINode(link.getFrom().getId()); UINode uito = deletedViewPaneUI.getUINode(link.getTo().getId()); NodeSummary from = link.getFrom(); NodeSummary to = link.getTo(); int permission = ICoreConstants.WRITE; String sOriginalID = ""; //$NON-NLS-1$ //add the link to the datamodel view LinkProperties innerlinkProps = (LinkProperties)deletedView.addMemberLink(type, sOriginalID, ProjectCompendium.APP.getModel().getUserProfile().getUserName(), from, to, link.getLabel(), linkProps); link.initialize(deletedView.getModel().getSession(), deletedView.getModel()); //create a link in UI layer - what about deleting the old object??? UILink newuilink = new UILink(link, innerlinkProps, uifrom, uito); ((UIMapViewFrame)deletedUIViewFrame).getViewPane().add(newuilink, (UIViewPane.LINK_LAYER)); //newuilink.setBounds(uilink.getPreferredBounds()); uifrom.addLink(newuilink); uito.addLink(newuilink); deletedViewPaneUI.addLink(innerlinkProps); } } deletedNodes.removeAllElements(); deletedLinks.removeAllElements(); } catch(Exception e) { log.error("Error...", e); ProjectCompendium.APP.displayError("Error: (PCEdit.restoreDeletedNodesAndLinks)\n\n" + e.getLocalizedMessage()); //$NON-NLS-1$ } } }