package test.org.korsakow.action;
import java.awt.Dimension;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import org.dsrg.soenea.uow.UoW;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.korsakow.domain.ImageFactory;
import org.korsakow.domain.InterfaceFactory;
import org.korsakow.domain.Project;
import org.korsakow.domain.ProjectFactory;
import org.korsakow.domain.SnuFactory;
import org.korsakow.domain.SoundFactory;
import org.korsakow.domain.TextFactory;
import org.korsakow.domain.VideoFactory;
import org.korsakow.domain.interf.IImage;
import org.korsakow.domain.interf.IInterface;
import org.korsakow.domain.interf.IProject;
import org.korsakow.domain.interf.IResource;
import org.korsakow.domain.interf.ISnu;
import org.korsakow.domain.interf.ISound;
import org.korsakow.domain.interf.IText;
import org.korsakow.domain.interf.IVideo;
import org.korsakow.domain.mapper.input.ResourceInputMapper;
import org.korsakow.ide.Application;
import org.korsakow.ide.resources.ResourceType;
import org.korsakow.ide.ui.components.tree.FolderNode;
import org.korsakow.ide.ui.components.tree.KNode;
import org.korsakow.ide.ui.components.tree.ResourceNode;
import org.korsakow.ide.ui.controller.action.DeleteAction;
import org.korsakow.ide.ui.dialogs.EditingConflictDialog;
import org.korsakow.ide.ui.resourceexplorer.ResourceTreeTable;
import org.korsakow.ide.ui.resourceexplorer.ResourceTreeTableModel;
import org.korsakow.ide.util.StrongReference;
import org.korsakow.ide.util.UIUtil;
import org.korsakow.ide.util.Util;
import test.org.korsakow.domain.AbstractDomainObjectTestCase;
import test.util.DomainTestUtil;
public class TestDeleteAction extends AbstractDomainObjectTestCase
{
private static boolean visualMode = false;
private MockApplication mockApp;
private JFrame frame;
private Random random;
private ResourceTreeTable treeTable;
private ResourceTreeTableModel model;
private Collection<IResource> domainList;
private Collection<KNode> nodeList;
private Collection<KNode> remainingNodes;
private Collection<KNode> selectedNodes;
@Override
@Before
public void setUp() throws Exception
{
final long SEED = System.nanoTime();
System.out.println(String.format("Random Seed: %d", SEED)); // printed in case you want/need to repro a particular run
random = new Random(SEED);
}
private void doInit(boolean dobreak) throws Exception {
UIUtil.runUITaskNowThrow(new UIUtil.RunnableThrow() {
public void run() throws Throwable {
TestDeleteAction.super.setUp();
Application.initializeInstance(mockApp = new MockApplication(false));
treeTable = new ResourceTreeTable();
treeTable.setAutoCreateColumnsFromModel(false);
model = treeTable.getTreeTableModel();
if (visualMode) {
frame = new JFrame("TestDeleteAction");
frame.setSize(480, 640);
frame.add(new JScrollPane(treeTable));
frame.pack();
frame.setVisible(true);
frame.toFront();
}
}
});
}
@Override
@After
public void tearDown() throws Exception
{
UIUtil.runUITaskNowThrow(new UIUtil.RunnableThrow() {
public void run() throws Throwable {
if (visualMode) {
frame.dispose();
frame = null;
}
Application.destroyInstance();
TestDeleteAction.super.tearDown();
}
});
treeTable = null;
model = null;
domainList = null;
nodeList = null;
selectedNodes = null;
}
@Test public void testDeleteEntireNonReferencingHierarchy() throws Throwable
{
doInit(true);
UIUtil.runUITaskNowThrow(new UIUtil.RunnableThrow() {
public void run() throws Exception {
createRandomHierarchy();
}
});
sleep(1000);
UIUtil.runUITaskNowThrow(new UIUtil.RunnableThrow() {
public void run() throws Exception {
selectedNodes = selectAll();
remainingNodes = getRemainingNodes(nodeList, selectedNodes);
Assert.assertTrue(remainingNodes.isEmpty());
}
});
sleep(2000);
UIUtil.runUITaskNowThrow(new UIUtil.RunnableThrow() {
public void run() throws Exception {
DeleteAction deleteAction = new DeleteAction(treeTable);
deleteAction.actionPerformed(null);
}
});
sleep(2000);
UIUtil.runUITaskNowThrow(new UIUtil.RunnableThrow() {
public void run() throws Exception {
assertDeleted(treeTable.getTreeTableModel(), Util.filterList(selectedNodes, new Util.Predicate<KNode>() {
public boolean execute(KNode node) {
return node instanceof ResourceNode &&
((ResourceNode)node).getResourceType() == ResourceType.SNU;
}
}));
assertNotDeleted(treeTable.getTreeTableModel(), remainingNodes);
}
});
}
@Test public void testDeleteSubSelectionOfNonReferencingHierarchy() throws Throwable
{
doInit(true);
UIUtil.runUITaskNowThrow(new UIUtil.RunnableThrow() {
public void run() throws Exception {
createRandomHierarchy();
}
});
sleep(1000);
UIUtil.runUITaskNowThrow(new UIUtil.RunnableThrow() {
public void run() throws Exception {
selectedNodes = selectRandomIntervals();
remainingNodes = getRemainingNodes(nodeList, selectedNodes);
}
});
sleep(2000);
UIUtil.runUITaskNowThrow(new UIUtil.RunnableThrow() {
public void run() throws Exception {
DeleteAction deleteAction = new DeleteAction(treeTable);
deleteAction.actionPerformed(null);
}
});
sleep(2000);
UIUtil.runUITaskNowThrow(new UIUtil.RunnableThrow() {
public void run() throws Exception {
assertDeleted(treeTable.getTreeTableModel(), Util.filterList(selectedNodes, new Util.Predicate<KNode>() {
public boolean execute(KNode node) {
return node instanceof ResourceNode &&
((ResourceNode)node).getResourceType() == ResourceType.SNU;
}
}));
assertNotDeleted(treeTable.getTreeTableModel(), remainingNodes);
}
});
}
@Test public void testDeleteSnuMainMedia() throws Throwable
{
doInit(false);
final StrongReference<KNode> mediaNodeRef = new StrongReference<KNode>();
UIUtil.runUITaskNowThrow(new UIUtil.RunnableThrow() {
public void run() throws Exception {
final Project project = ProjectFactory.createNew();
UoW.getCurrent().registerNew( project );
IVideo media = VideoFactory.createNew();
DomainTestUtil.initializeRandom(media);
ISnu snu = SnuFactory.createNew();
DomainTestUtil.initializeRandom(snu);
snu.setMainMedia(media);
IInterface interf = InterfaceFactory.createNew();
snu.setInterface(interf);
UoW.getCurrent().commit();
UoW.newCurrent();
// Video appMedia = DomainToApp.domainToApp(media);
// Snu appSnu = DomainToApp.domainToApp(snu);
KNode mediaNode = ResourceNode.create( media );
model.appendNode( mediaNode, model.getRoot() );
KNode snuNode = ResourceNode.create( snu );
model.appendNode( snuNode, model.getRoot() );
mediaNodeRef.set(mediaNode);
treeTable.expandAllRecursive();
nodeList = new ArrayList<KNode>();
nodeList.add(mediaNode);
nodeList.add(snuNode);
}
});
sleep(1000);
UIUtil.runUITaskNowThrow(new UIUtil.RunnableThrow() {
public void run() throws Exception {
int mediaRow = treeTable.getRow(mediaNodeRef.get());
treeTable.getSelectionModel().setSelectionInterval(mediaRow, mediaRow);
selectedNodes = Arrays.asList(mediaNodeRef.get());
remainingNodes = getRemainingNodes(nodeList, selectedNodes);
}
});
sleep(2000);
UIUtil.runUITaskNowThrow(new UIUtil.RunnableThrow() {
public void run() throws Exception {
DeleteAction deleteAction = new DeleteAction(treeTable);
deleteAction.actionPerformed(null);
}
});
sleep(2000);
UIUtil.runUITaskNowThrow(new UIUtil.RunnableThrow() {
public void run() throws Exception {
assertDeleted(treeTable.getTreeTableModel(), selectedNodes);
assertNotDeleted(treeTable.getTreeTableModel(), remainingNodes);
}
});
}
private void sleep(long time) throws InterruptedException
{
if (visualMode)
Thread.sleep(time);
}
private Collection<KNode> selectRandomIntervals() throws Exception
{
Assert.assertTrue(SwingUtilities.isEventDispatchThread());
int rowCount = treeTable.getRowCount();
List<Integer> rows = new ArrayList<Integer>();
for (int i = 0; i < rowCount; ++i)
rows.add(i);
Collections.shuffle(rows);
int N = (int)Math.ceil(rowCount / 2.0); // ceil ensures non-zero
rows = rows.subList(0, N);
treeTable.clearSelection();
for (int i = 0; i < N; ++i)
treeTable.getSelectionModel().addSelectionInterval(rows.get(i), rows.get(i));
return (Collection<KNode>)treeTable.getSelectedNodes();
}
private Collection<KNode> selectAll() throws Exception
{
Assert.assertTrue(SwingUtilities.isEventDispatchThread());
int rowCount = treeTable.getRowCount();
treeTable.clearSelection();
treeTable.getSelectionModel().addSelectionInterval(0, rowCount-1);
return (Collection<KNode>)treeTable.getSelectedNodes();
}
private void createRandomHierarchy() throws Exception
{
IProject project = ProjectFactory.createNew();
DomainTestUtil.initializeRandom(project);
UoW.getCurrent().registerNew(project);
Assert.assertTrue(SwingUtilities.isEventDispatchThread());
Collection<IResource> domainObjects = new HashSet<IResource>();
int N = 11 + random.nextInt(10);
for (int i = 0; i < N; ++i)
{
int M = random.nextInt(3);
IResource resource = null;
switch (M)
{
case 0:
case 1:
resource = VideoFactory.createNew();
DomainTestUtil.initializeRandom((IVideo)resource);
break;
case 2:
resource = ImageFactory.createNew();
DomainTestUtil.initializeRandom((IImage)resource);
break;
case 3:
resource = SoundFactory.createNew();
DomainTestUtil.initializeRandom((ISound)resource);
break;
case 4:
resource = TextFactory.createNew();
DomainTestUtil.initializeRandom((IText)resource);
break;
// case 5:
// resource = PatternFactory.createNew();
// DomainTestUtil.initializeRandom((IPattern)resource);
// break;
}
domainObjects.add(resource);
}
Assert.assertFalse(domainObjects.isEmpty());
UoW.getCurrent().commit();
UoW.newCurrent();
nodeList = new HashSet<KNode>();
FolderNode currentFolder = model.getRoot();
for (IResource obj : domainObjects)
{
if (random.nextBoolean()) {
FolderNode parent = currentFolder;
currentFolder = new FolderNode(DomainTestUtil.getRandomString());
model.appendNode(currentFolder, parent);
} else {
if (random.nextBoolean())
currentFolder = model.getRoot();
}
KNode node = ResourceNode.create(obj);
model.appendNode(node, currentFolder);
nodeList.add(node);
}
treeTable.expandAllRecursive();
Assert.assertFalse(nodeList.isEmpty());
domainList = domainObjects;
}
private static void assertDeleted(ResourceTreeTableModel model, Collection<KNode> nodes) throws Exception
{
for (KNode node : nodes)
{
// ui layer
Assert.assertTrue(model.isValidTreeTableNode(node));
if (node instanceof ResourceNode) {
ResourceNode resourceNode = (ResourceNode)node;
// domain layer
ResourceInputMapper.map(resourceNode.getResourceId());
}
}
}
private static void assertNotDeleted(ResourceTreeTableModel model, Collection<KNode> nodes) throws Exception
{
for (KNode node : nodes)
{
// ui layer
Assert.assertTrue(node.getClass().getSimpleName() + ": " + node.getName(), model.isValidTreeTableNode(node));
if (node instanceof ResourceNode) {
ResourceNode resourceNode = (ResourceNode)node;
// domain layer
ResourceInputMapper.map(resourceNode.getResourceId());
}
}
}
/**
* Filters out any nodes that were deleted because their parent was selected.
* @param fullList
* @param deletedList
* @return
*/
private static Collection<KNode> getRemainingNodes(Collection<KNode> fullList, Collection<KNode> deletedList) {
Collection<KNode> notDeleted = new HashSet<KNode>(fullList);
for (KNode node : fullList) {
if (deletedList.contains(node)) {
notDeleted.remove(node);
continue;
}
for (KNode sel : deletedList) {
if (node.isNodeAncestor(sel)) {
notDeleted.remove(node);
break;
}
}
}
return notDeleted;
}
private static class MockApplication extends Application
{
public boolean alerted = false;
public MockEditingConflictDialog dialog;
public boolean dobreak;
protected MockApplication(boolean dobreak) throws Exception {
super();
this.dobreak = dobreak;
}
@Override
public EditingConflictDialog showEditingConflictDialog()
{
dialog = new MockEditingConflictDialog(getProjectExplorer(), dobreak);
dialog.setTitle("Editing Conflict");
dialog.setModal(true);
dialog.setSize(new Dimension(320, 240));
UIUtil.centerOnFrame(dialog, getProjectExplorer());
return dialog;
}
public void showAlertDialog(String title, String message) {
alerted = true;
}
}
private static class MockEditingConflictDialog extends EditingConflictDialog
{
boolean dobreak;
public MockEditingConflictDialog(JFrame parent, boolean dobreak) {
super(parent);
this.dobreak = dobreak;
}
@Override
public void show()
{
UIUtil.runUITaskLater(new Runnable() {
public void run() {
try { Thread.sleep(100); } catch (InterruptedException e) {}
if (dobreak)
breakLinksButton.doClick();
else
cancelButton.doClick();
}
});
super.show();
}
}
}