Skip to content

Commit

Permalink
Implement #1436 duplicate workspace and #2667
Browse files Browse the repository at this point in the history
  • Loading branch information
mbastian committed Nov 9, 2022
1 parent b910ea9 commit 9a79ee9
Show file tree
Hide file tree
Showing 10 changed files with 174 additions and 142 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,12 @@ Development and Distribution License("CDDL") (collectively, the
import org.gephi.project.api.ProjectListener;
import org.gephi.project.api.Workspace;
import org.gephi.project.api.WorkspaceListener;
import org.gephi.project.io.DuplicateTask;
import org.gephi.project.io.LoadTask;
import org.gephi.project.io.SaveTask;
import org.gephi.project.spi.WorkspaceDuplicateProvider;
import org.gephi.utils.longtask.api.LongTaskExecutor;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.util.lookup.ServiceProvider;

/**
Expand Down Expand Up @@ -374,15 +375,25 @@ public Workspace openNewWorkspace() {
@Override
public Workspace duplicateWorkspace(Workspace workspace) {
synchronized (this) {
if (projects.hasCurrentProject()) {
Workspace duplicate = newWorkspace(projects.getCurrentProject());
for (WorkspaceDuplicateProvider dp : Lookup.getDefault().lookupAll(WorkspaceDuplicateProvider.class)) {
dp.duplicate(workspace, duplicate);
DuplicateTask duplicateTask = new DuplicateTask(workspace);
Future<WorkspaceImpl> res = longTaskExecutor.execute(duplicateTask, () -> {
WorkspaceImpl newWorkspace = duplicateTask.run();
// Null if cancelled
if (newWorkspace != null) {
newWorkspace.getLookup().lookup(WorkspaceInformationImpl.class).setName(
NbBundle.getMessage(ProjectControllerImpl.class, "Workspace.duplicated.name",
workspace.getName()));
fireWorkspaceEvent(EventType.INITIALIZE, newWorkspace);

openWorkspace(newWorkspace);
}
openWorkspace(duplicate);
return duplicate;
return newWorkspace;
}, "", t -> handleException(workspace.getProject(), t));
try {
return res.get();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
return null;
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package org.gephi.project.io;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.util.Collection;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
import org.gephi.project.api.Workspace;
import org.gephi.project.impl.ProjectImpl;
import org.gephi.project.impl.WorkspaceImpl;
import org.gephi.project.spi.WorkspaceBytesPersistenceProvider;
import org.gephi.project.spi.WorkspacePersistenceProvider;
import org.gephi.project.spi.WorkspaceXMLPersistenceProvider;
import org.gephi.utils.longtask.spi.LongTask;
import org.gephi.utils.progress.Progress;
import org.gephi.utils.progress.ProgressTicket;
import org.openide.util.NbBundle;

public class DuplicateTask implements LongTask {

private final Workspace workspace;

private boolean cancel = false;

private ProgressTicket progressTicket;

public DuplicateTask(Workspace workspace) {
this.workspace = workspace;
}

public WorkspaceImpl run() {
Progress.start(progressTicket);
Progress.setDisplayName(progressTicket, NbBundle.getMessage(DuplicateTask.class, "DuplicateTask.name"));

try {
WorkspaceImpl newWorkspace = duplicateWorkspace(workspace);

Collection<WorkspacePersistenceProvider> providers = PersistenceProviderUtils.getPersistenceProviders();

for (WorkspacePersistenceProvider provider : providers) {
if (!cancel) {
if (provider instanceof WorkspaceXMLPersistenceProvider) {
duplicateWorkspaceModel(workspace, newWorkspace, (WorkspaceXMLPersistenceProvider) provider);
} else if (provider instanceof WorkspaceBytesPersistenceProvider) {
duplicateWorkspaceModel(workspace, newWorkspace, (WorkspaceBytesPersistenceProvider) provider);
}
}
}

return newWorkspace;
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
Progress.finish(progressTicket);
}
}

private void duplicateWorkspaceModel(Workspace workspace, Workspace newWorkspace,
WorkspaceBytesPersistenceProvider persistenceProvider) throws Exception {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
persistenceProvider.writeBytes(dos, workspace);
bos.close();

ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
DataInputStream dis = new DataInputStream(bis);
persistenceProvider.readBytes(dis, newWorkspace);
bis.close();
}

private void duplicateWorkspaceModel(Workspace workspace, Workspace newWorkspace,
WorkspaceXMLPersistenceProvider persistenceProvider) throws Exception {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
XMLStreamWriter writer = SaveTask.newXMLWriter(bos);
GephiWriter.writeWorkspaceChildren(writer, workspace, persistenceProvider);
writer.close();
bos.close();

ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
XMLStreamReader reader = LoadTask.newXMLReader(bis);
GephiReader.readWorkspaceChildren(newWorkspace, reader, persistenceProvider);
reader.close();
bis.close();
}

private WorkspaceImpl duplicateWorkspace(Workspace workspace) throws Exception {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
XMLStreamWriter writer = SaveTask.newXMLWriter(bos);
GephiWriter.writeWorkspace(writer, workspace);
writer.close();
bos.flush();

ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
XMLStreamReader reader = LoadTask.newXMLReader(bis);
WorkspaceImpl newWorkspace = GephiReader.readWorkspace(reader, (ProjectImpl) workspace.getProject());
reader.close();
bis.close();
return newWorkspace;
}

@Override
public boolean cancel() {
cancel = true;
return true;
}

@Override
public void setProgressTicket(ProgressTicket progressTicket) {
this.progressTicket = progressTicket;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ public static WorkspaceImpl readWorkspace(XMLStreamReader reader, ProjectImpl pr
if ("workspace".equalsIgnoreCase(name)) {
//Id
Integer workspaceId;
if (reader.getAttributeValue(null, "id") == null) {
if (reader.getAttributeValue(null, "id") == null ||
project.getWorkspace(Integer.parseInt(reader.getAttributeValue(null, "id"))) != null) {
workspaceId = project.nextWorkspaceId();
} else {
workspaceId = Integer.parseInt(reader.getAttributeValue(null, "id"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,22 @@ public LoadTask(File file) {
this.file = file;
}

public static XMLStreamReader newXMLReader(InputStream is) throws XMLStreamException {
XMLInputFactory inputFactory = XMLInputFactory.newInstance();
if (inputFactory.isPropertySupported("javax.xml.stream.isValidating")) {
inputFactory.setProperty("javax.xml.stream.isValidating", Boolean.FALSE);
}
inputFactory.setXMLReporter(new XMLReporter() {
@Override
public void report(String message, String errorType, Object relatedInformation,
Location location) throws XMLStreamException {
}
});
InputStreamReader isReader = new InputStreamReader(is, StandardCharsets.UTF_8);
Xml10FilterReader filterReader = new Xml10FilterReader(isReader);
return inputFactory.createXMLStreamReader(filterReader);
}

public ProjectImpl execute(ProjectsImpl projects) {
Progress.start(progressTicket);
Progress.setDisplayName(progressTicket, NbBundle.getMessage(LoadTask.class, "LoadTask.name"));
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
Services/MIMEResolver/GephiResolver.xml=Gephi Files
Templates/Other/GephiTemplate.gephi=Empty Gephi file
Project.default.prefix=Untitled
Workspace.default.prefix=Workspace
Workspace.default.prefix=Workspace
Workspace.duplicated.name=Copy of {0}
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ Templates/Other/GephiTemplate.gephi=Empty Gephi file

LoadTask.name=Opening project
SaveTask.name=Saving project
DuplicateTask.name=Duplicating workspace
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,24 @@ public void testOpenAnotherProject() throws IOException {
Mockito.verify(workspaceListener).initialize(pc.getCurrentWorkspace());
}

@Test
public void testDuplicateWorkspace() {
MockServices.setServices(MockController.class);

ProjectControllerImpl pc = new ProjectControllerImpl();
pc.addWorkspaceListener(workspaceListener);
pc.newProject();
Workspace duplicate = pc.duplicateWorkspace(pc.getCurrentWorkspace());
Assert.assertNotNull(duplicate);
Assert.assertTrue(duplicate.isOpen());
Assert.assertSame(duplicate, pc.getCurrentWorkspace());
Assert.assertEquals(2, pc.getCurrentProject().getWorkspaces().size());
Mockito.verify(workspaceListener).initialize(duplicate);
Mockito.verify(workspaceListener).select(duplicate);
Assert.assertNotNull(duplicate.getLookup().lookup(MockModel.class));

}

public static class MockModel implements Model {

private final Workspace workspace;
Expand Down
1 change: 1 addition & 0 deletions src/main/javadoc/overview.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ <h4>Project API</h4>
<li>Deprecation of <code>ProjectInformation</code>. Relevant methods have been ported to <code>Project</code>.</li>
<li>Also deprecation of <code>WorkspaceInformation</code>. Relevant methods have been ported to <code>Workspace</code>.</li>
<li>Finally, deprecation of <code>WorkspaceProvider</code>. Relevant methods were ported to <code>Project</code>.</li>
<li>The duplication of workspaces is now managed through existing persistence providers. Therefore the <code>WorkspaceDuplicateProvider</code> SPI has been removed.</li>
</ul>
<h4>LongTask API</h4>
<ul>
Expand Down

0 comments on commit 9a79ee9

Please sign in to comment.