From 2aa35be755c2f189d7d078cb82b760350a8f76ee Mon Sep 17 00:00:00 2001 From: Mathieu Bastian Date: Sun, 12 May 2013 10:48:19 -0700 Subject: [PATCH] Add support for bytes workspace persistence provider data --- .../org/gephi/project/io/GephiReader.java | 27 +----- .../org/gephi/project/io/GephiWriter.java | 19 +--- .../java/org/gephi/project/io/LoadTask.java | 93 +++++++++++++++---- .../project/io/PersistenceProviderUtils.java | 83 +++++++++++++++++ .../java/org/gephi/project/io/SaveTask.java | 40 ++++++-- .../WorkspaceBytesPersistenceProvider.java | 86 +++++++++++++++++ 6 files changed, 286 insertions(+), 62 deletions(-) create mode 100644 modules/ProjectAPI/src/main/java/org/gephi/project/io/PersistenceProviderUtils.java create mode 100644 modules/ProjectAPI/src/main/java/org/gephi/project/spi/WorkspaceBytesPersistenceProvider.java diff --git a/modules/ProjectAPI/src/main/java/org/gephi/project/io/GephiReader.java b/modules/ProjectAPI/src/main/java/org/gephi/project/io/GephiReader.java index f39e3f45e..29e3f926c 100644 --- a/modules/ProjectAPI/src/main/java/org/gephi/project/io/GephiReader.java +++ b/modules/ProjectAPI/src/main/java/org/gephi/project/io/GephiReader.java @@ -41,11 +41,8 @@ */ package org.gephi.project.io; -import java.util.LinkedHashMap; -import java.util.Map; import javax.xml.stream.XMLStreamReader; import javax.xml.stream.events.XMLEvent; -import org.gephi.project.api.Project; import org.gephi.project.api.Workspace; import org.gephi.project.impl.ProjectControllerImpl; import org.gephi.project.impl.ProjectImpl; @@ -63,7 +60,6 @@ import org.openide.util.Lookup; */ public class GephiReader implements Cancellable { - private ProjectImpl project; private boolean cancel = false; private WorkspacePersistenceProvider currentProvider; @@ -73,7 +69,8 @@ public class GephiReader implements Cancellable { return true; } - public Project readProject(XMLStreamReader reader, ProjectsImpl projects) throws Exception { + public ProjectImpl readProject(XMLStreamReader reader, ProjectsImpl projects) throws Exception { + ProjectImpl project = null; boolean end = false; while (reader.hasNext() && !end) { Integer eventType = reader.next(); @@ -87,7 +84,7 @@ public class GephiReader implements Cancellable { } } else if ("project".equalsIgnoreCase(name)) { String projectName = reader.getAttributeValue(null, "name"); - this.project = new ProjectImpl(projectName); + project = new ProjectImpl(projectName); project.getLookup().lookup(WorkspaceProviderImpl.class); if (reader.getAttributeValue(null, "ids") != null) { @@ -105,7 +102,7 @@ public class GephiReader implements Cancellable { return project; } - public Workspace readWorkspace(XMLStreamReader reader) throws Exception { + public Workspace readWorkspace(XMLStreamReader reader, ProjectImpl project) throws Exception { WorkspaceImpl workspace = null; boolean end = false; while (reader.hasNext() && !end) { @@ -177,7 +174,7 @@ public class GephiReader implements Cancellable { Integer eventType = reader.next(); if (eventType.equals(XMLEvent.START_ELEMENT)) { String name = reader.getLocalName(); - WorkspacePersistenceProvider pp = getPersistenceProviders().get(name); + WorkspacePersistenceProvider pp = PersistenceProviderUtils.getXMLPersistenceProviders().get(name); if (pp != null) { currentProvider = pp; try { @@ -193,18 +190,4 @@ public class GephiReader implements Cancellable { } } } - - private Map getPersistenceProviders() { - Map providers = new LinkedHashMap(); - for (WorkspacePersistenceProvider w : Lookup.getDefault().lookupAll(WorkspacePersistenceProvider.class)) { - try { - String id = w.getIdentifier(); - if (id != null && !id.isEmpty()) { - providers.put(w.getIdentifier(), w); - } - } catch (Exception e) { - } - } - return providers; - } } diff --git a/modules/ProjectAPI/src/main/java/org/gephi/project/io/GephiWriter.java b/modules/ProjectAPI/src/main/java/org/gephi/project/io/GephiWriter.java index 13807215a..c80119407 100644 --- a/modules/ProjectAPI/src/main/java/org/gephi/project/io/GephiWriter.java +++ b/modules/ProjectAPI/src/main/java/org/gephi/project/io/GephiWriter.java @@ -44,7 +44,6 @@ package org.gephi.project.io; import java.text.MessageFormat; import java.text.SimpleDateFormat; import java.util.Calendar; -import java.util.LinkedHashMap; import java.util.Map; import java.util.TimeZone; import javax.xml.stream.XMLStreamWriter; @@ -56,7 +55,6 @@ import org.gephi.project.api.WorkspaceInformation; import org.gephi.project.impl.ProjectImpl; import org.gephi.project.spi.WorkspacePersistenceProvider; import org.openide.util.Cancellable; -import org.openide.util.Lookup; import org.openide.util.NbBundle; /** @@ -120,6 +118,7 @@ public class GephiWriter implements Cancellable { writer.writeStartElement("workspace"); writer.writeAttribute("name", info.getName()); + writer.writeAttribute("id", String.valueOf(workspace.getId())); if (info.isOpen()) { writer.writeAttribute("status", "open"); } else if (info.isClosed()) { @@ -137,7 +136,7 @@ public class GephiWriter implements Cancellable { } public void writeWorkspaceChildren(XMLStreamWriter writer, Workspace workspace) throws Exception { - for (Map.Entry entry : getPersistenceProviders().entrySet()) { + for (Map.Entry entry : PersistenceProviderUtils.getXMLPersistenceProviders().entrySet()) { try { String identifier = entry.getKey(); WorkspacePersistenceProvider pp = entry.getValue(); @@ -163,20 +162,6 @@ public class GephiWriter implements Cancellable { writer.writeComment("File saved with " + getVersion()); } - private Map getPersistenceProviders() { - Map providers = new LinkedHashMap(); - for (WorkspacePersistenceProvider w : Lookup.getDefault().lookupAll(WorkspacePersistenceProvider.class)) { - try { - String id = w.getIdentifier(); - if (id != null && !id.isEmpty()) { - providers.put(w.getIdentifier(), w); - } - } catch (Exception e) { - } - } - return providers; - } - private String getVersion() { try { return MessageFormat.format( diff --git a/modules/ProjectAPI/src/main/java/org/gephi/project/io/LoadTask.java b/modules/ProjectAPI/src/main/java/org/gephi/project/io/LoadTask.java index f0f7132e4..35a930016 100644 --- a/modules/ProjectAPI/src/main/java/org/gephi/project/io/LoadTask.java +++ b/modules/ProjectAPI/src/main/java/org/gephi/project/io/LoadTask.java @@ -41,11 +41,14 @@ */ package org.gephi.project.io; +import java.io.DataInputStream; import java.io.File; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.Charset; import java.util.Enumeration; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import javax.xml.stream.Location; @@ -53,10 +56,13 @@ import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLReporter; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; -import org.gephi.project.api.Project; +import org.gephi.project.api.Workspace; import org.gephi.project.impl.ProjectControllerImpl; +import org.gephi.project.impl.ProjectImpl; import org.gephi.project.impl.ProjectInformationImpl; import org.gephi.project.impl.ProjectsImpl; +import org.gephi.project.impl.WorkspaceProviderImpl; +import org.gephi.project.spi.WorkspaceBytesPersistenceProvider; import org.gephi.utils.longtask.spi.LongTask; import org.gephi.utils.progress.Progress; import org.gephi.utils.progress.ProgressTicket; @@ -84,7 +90,7 @@ public class LoadTask implements LongTask, Runnable { Progress.setDisplayName(progressTicket, NbBundle.getMessage(LoadTask.class, "LoadTask.name")); try { - Project project = null; + ProjectImpl project = null; ZipFile zip = null; try { zip = new ZipFile(file, Charset.forName("UTF-8")); @@ -92,26 +98,63 @@ public class LoadTask implements LongTask, Runnable { //Reader gephiReader = new GephiReader(); - for (Enumeration e = zip.entries(); e.hasMoreElements();) { - ZipEntry entry = e.nextElement(); + //Project + ZipEntry entry = zip.getEntry("Project_xml"); + if (entry != null) { InputStream is = null; - try { is = zip.getInputStream(entry); - String name = entry.getName(); - if (name.equals("Project_xml")) { - project = readProject(is); - } else if (name.contains("Workspace") && name.contains("xml")) { - readWorkspace(is); - } + project = readProject(is); } finally { if (is != null) { is.close(); } } + } - if (cancel) { - break; + //Workspace Xml + if (project != null) { + for (Enumeration e = zip.entries(); e.hasMoreElements();) { + entry = e.nextElement(); + InputStream is = null; + String name = entry.getName(); + if (name.matches("Workspace_[0-9]*_xml")) { + try { + is = zip.getInputStream(entry); + readWorkspace(is, project); + } finally { + if (is != null) { + is.close(); + } + } + } + } + } + + //Other Workspace data + if (project != null) { + for (Enumeration e = zip.entries(); e.hasMoreElements();) { + entry = e.nextElement(); + InputStream is = null; + String name = entry.getName(); + if (name.matches("Workspace_[0-9]*_.*_bytes")) { + try { + is = zip.getInputStream(entry); + Matcher matcher = Pattern.compile("Workspace_([0-9]*)_(.*)_bytes").matcher(name); + matcher.find(); + String workspaceId = matcher.group(1); + String providerId = matcher.group(2); + WorkspaceProviderImpl workspaceProvider = project.getLookup().lookup(WorkspaceProviderImpl.class); + Workspace workspace = workspaceProvider.getWorkspace(Integer.parseInt(workspaceId)); + if (workspace != null) { + readWorkspaceBytes(is, workspace, providerId); + } + } finally { + if (is != null) { + is.close(); + } + } + } } } @@ -136,7 +179,7 @@ public class LoadTask implements LongTask, Runnable { Progress.finish(progressTicket); } - private Project readProject(InputStream inputStream) throws Exception { + private ProjectImpl readProject(InputStream inputStream) throws Exception { InputStreamReader isReader = null; Xml10FilterReader filterReader = null; XMLStreamReader reader = null; @@ -157,7 +200,7 @@ public class LoadTask implements LongTask, Runnable { ProjectControllerImpl projectController = Lookup.getDefault().lookup(ProjectControllerImpl.class); ProjectsImpl projects = projectController.getProjects(); - Project project = gephiReader.readProject(reader, projects); + ProjectImpl project = gephiReader.readProject(reader, projects); project.getLookup().lookup(ProjectInformationImpl.class).setFile(file); return project; } finally { @@ -170,7 +213,7 @@ public class LoadTask implements LongTask, Runnable { } } - private void readWorkspace(InputStream inputStream) throws Exception { + private void readWorkspace(InputStream inputStream, ProjectImpl project) throws Exception { InputStreamReader isReader = null; Xml10FilterReader filterReader = null; XMLStreamReader reader = null; @@ -189,7 +232,7 @@ public class LoadTask implements LongTask, Runnable { filterReader = new Xml10FilterReader(isReader); reader = inputFactory.createXMLStreamReader(filterReader); - gephiReader.readWorkspace(reader); + gephiReader.readWorkspace(reader, project); } finally { if (reader != null) { reader.close(); @@ -203,6 +246,22 @@ public class LoadTask implements LongTask, Runnable { } } + private void readWorkspaceBytes(InputStream inputstream, Workspace workspace, String providerId) throws Exception { + WorkspaceBytesPersistenceProvider provider = PersistenceProviderUtils.getBytesPersistenceProviders().get(providerId); + + if (provider != null) { + DataInputStream stream = null; + try { + stream = new DataInputStream(inputstream); + provider.readBytes(stream, workspace); + } finally { + if (stream != null) { + stream.close(); + } + } + } + } + @Override public boolean cancel() { cancel = true; diff --git a/modules/ProjectAPI/src/main/java/org/gephi/project/io/PersistenceProviderUtils.java b/modules/ProjectAPI/src/main/java/org/gephi/project/io/PersistenceProviderUtils.java new file mode 100644 index 000000000..93dedc9be --- /dev/null +++ b/modules/ProjectAPI/src/main/java/org/gephi/project/io/PersistenceProviderUtils.java @@ -0,0 +1,83 @@ +/* + Copyright 2008-2010 Gephi + Authors : Mathieu Bastian + Website : http://www.gephi.org + + This file is part of Gephi. + + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + + Copyright 2011 Gephi Consortium. All rights reserved. + + The contents of this file are subject to the terms of either the GNU + General Public License Version 3 only ("GPL") or the Common + Development and Distribution License("CDDL") (collectively, the + "License"). You may not use this file except in compliance with the + License. You can obtain a copy of the License at + http://gephi.org/about/legal/license-notice/ + or /cddl-1.0.txt and /gpl-3.0.txt. See the License for the + specific language governing permissions and limitations under the + License. When distributing the software, include this License Header + Notice in each file and include the License files at + /cddl-1.0.txt and /gpl-3.0.txt. If applicable, add the following below the + License Header, with the fields enclosed by brackets [] replaced by + your own identifying information: + "Portions Copyrighted [year] [name of copyright owner]" + + If you wish your version of this file to be governed by only the CDDL + or only the GPL Version 3, indicate your decision by adding + "[Contributor] elects to include this software in this distribution + under the [CDDL or GPL Version 3] license." If you do not indicate a + single choice of license, a recipient has the option to distribute + your version of this file under either the CDDL, the GPL Version 3 or + to extend the choice of license to its licensees as provided above. + However, if you add GPL Version 3 code and therefore, elected the GPL + Version 3 license, then the option applies only if the new code is + made subject to such option by the copyright holder. + + Contributor(s): + + Portions Copyrighted 2011 Gephi Consortium. + */ +package org.gephi.project.io; + +import java.util.LinkedHashMap; +import java.util.Map; +import org.gephi.project.spi.WorkspaceBytesPersistenceProvider; +import org.gephi.project.spi.WorkspacePersistenceProvider; +import org.openide.util.Lookup; + +/** + * + * @author mbastian + */ +public class PersistenceProviderUtils { + + public static Map getXMLPersistenceProviders() { + Map providers = new LinkedHashMap(); + for (WorkspacePersistenceProvider w : Lookup.getDefault().lookupAll(WorkspacePersistenceProvider.class)) { + try { + String id = w.getIdentifier(); + if (id != null && !id.isEmpty()) { + providers.put(w.getIdentifier(), w); + } + } catch (Exception e) { + } + } + return providers; + } + + public static Map getBytesPersistenceProviders() { + Map providers = new LinkedHashMap(); + for (WorkspaceBytesPersistenceProvider w : Lookup.getDefault().lookupAll(WorkspaceBytesPersistenceProvider.class)) { + try { + String id = w.getIdentifier(); + if (id != null && !id.isEmpty()) { + providers.put(w.getIdentifier(), w); + } + } catch (Exception e) { + } + } + return providers; + } +} diff --git a/modules/ProjectAPI/src/main/java/org/gephi/project/io/SaveTask.java b/modules/ProjectAPI/src/main/java/org/gephi/project/io/SaveTask.java index bcc3468c4..4b12cb01c 100644 --- a/modules/ProjectAPI/src/main/java/org/gephi/project/io/SaveTask.java +++ b/modules/ProjectAPI/src/main/java/org/gephi/project/io/SaveTask.java @@ -42,10 +42,13 @@ package org.gephi.project.io; import java.io.BufferedOutputStream; +import java.io.DataOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; +import java.io.OutputStream; import java.nio.charset.Charset; +import java.util.Map; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; import javax.xml.stream.XMLOutputFactory; @@ -53,6 +56,7 @@ import javax.xml.stream.XMLStreamWriter; import org.gephi.project.api.Project; import org.gephi.project.api.Workspace; import org.gephi.project.impl.WorkspaceProviderImpl; +import org.gephi.project.spi.WorkspaceBytesPersistenceProvider; import org.gephi.utils.longtask.spi.LongTask; import org.gephi.utils.progress.Progress; import org.gephi.utils.progress.ProgressTicket; @@ -93,6 +97,7 @@ public class SaveTask implements LongTask, Runnable { FileOutputStream outputStream = null; ZipOutputStream zipOut = null; BufferedOutputStream bos = null; + DataOutputStream dos = null; try { //Stream int zipLevel = NbPreferences.forModule(SaveTask.class).getInt(ZIP_LEVEL_PREFERENCE, 9); @@ -100,6 +105,7 @@ public class SaveTask implements LongTask, Runnable { zipOut = new ZipOutputStream(outputStream, Charset.forName("UTF-8")); zipOut.setLevel(zipLevel); bos = new BufferedOutputStream(zipOut); + dos = new DataOutputStream(bos); //Writer gephiWriter = new GephiWriter(); @@ -109,7 +115,8 @@ public class SaveTask implements LongTask, Runnable { //Write Workspace files for (Workspace ws : project.getLookup().lookup(WorkspaceProviderImpl.class).getWorkspaces()) { - writeWorkspace(ws, gephiWriter, bos, zipOut); + writeWorkspace(ws, gephiWriter, dos, zipOut); + writeWorkspaceBytes(ws, dos, zipOut); if (cancel) { break; } @@ -117,6 +124,12 @@ public class SaveTask implements LongTask, Runnable { zipOut.finish(); } finally { + if (dos != null) { + try { + dos.close(); + } catch (IOException ex1) { + } + } if (bos != null) { try { bos.close(); @@ -171,7 +184,7 @@ public class SaveTask implements LongTask, Runnable { Progress.finish(progressTicket); } - private void writeProject(GephiWriter gephiWriter, BufferedOutputStream bufferedOutputStream, ZipOutputStream zipOut) throws Exception { + private void writeProject(GephiWriter gephiWriter, OutputStream outputStream, ZipOutputStream zipOut) throws Exception { XMLStreamWriter writer = null; //Write Project file zipOut.putNextEntry(new ZipEntry("Project_xml")); @@ -179,7 +192,7 @@ public class SaveTask implements LongTask, Runnable { //Create Writer and write project XMLOutputFactory outputFactory = XMLOutputFactory.newInstance(); outputFactory.setProperty("javax.xml.stream.isRepairingNamespaces", Boolean.FALSE); - writer = outputFactory.createXMLStreamWriter(bufferedOutputStream, "UTF-8"); + writer = outputFactory.createXMLStreamWriter(outputStream, "UTF-8"); gephiWriter.writeProject(writer, project); } finally { if (writer != null) { @@ -191,16 +204,16 @@ public class SaveTask implements LongTask, Runnable { zipOut.closeEntry(); } - private void writeWorkspace(Workspace workspace, GephiWriter gephiWriter, BufferedOutputStream bufferedOutputStream, ZipOutputStream zipOut) throws Exception { + private void writeWorkspace(Workspace workspace, GephiWriter gephiWriter, OutputStream outputStream, ZipOutputStream zipOut) throws Exception { //Write Project file - zipOut.putNextEntry(new ZipEntry("Workspace" + workspace.getId() + "_xml")); + zipOut.putNextEntry(new ZipEntry("Workspace_" + workspace.getId() + "_xml")); XMLStreamWriter writer = null; try { //Create Writer and write project XMLOutputFactory outputFactory = XMLOutputFactory.newInstance(); outputFactory.setProperty("javax.xml.stream.isRepairingNamespaces", Boolean.FALSE); - writer = outputFactory.createXMLStreamWriter(bufferedOutputStream, "UTF-8"); + writer = outputFactory.createXMLStreamWriter(outputStream, "UTF-8"); gephiWriter.writeWorkspace(writer, workspace); } finally { @@ -213,6 +226,21 @@ public class SaveTask implements LongTask, Runnable { zipOut.closeEntry(); } + private void writeWorkspaceBytes(Workspace workspace, DataOutputStream outputStream, ZipOutputStream zipOut) throws Exception { + for (Map.Entry entry : PersistenceProviderUtils.getBytesPersistenceProviders().entrySet()) { + String name = entry.getKey(); + WorkspaceBytesPersistenceProvider provider = entry.getValue(); + + //Write Project file + zipOut.putNextEntry(new ZipEntry("Workspace_" + workspace.getId() + "_" + name + "_bytes")); + + provider.writeBytes(outputStream, workspace); + + //Close Project file + zipOut.closeEntry(); + } + } + @Override public boolean cancel() { if (gephiWriter != null) { diff --git a/modules/ProjectAPI/src/main/java/org/gephi/project/spi/WorkspaceBytesPersistenceProvider.java b/modules/ProjectAPI/src/main/java/org/gephi/project/spi/WorkspaceBytesPersistenceProvider.java new file mode 100644 index 000000000..aef590348 --- /dev/null +++ b/modules/ProjectAPI/src/main/java/org/gephi/project/spi/WorkspaceBytesPersistenceProvider.java @@ -0,0 +1,86 @@ +/* + Copyright 2008-2010 Gephi + Authors : Mathieu Bastian + Website : http://www.gephi.org + + This file is part of Gephi. + + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + + Copyright 2011 Gephi Consortium. All rights reserved. + + The contents of this file are subject to the terms of either the GNU + General Public License Version 3 only ("GPL") or the Common + Development and Distribution License("CDDL") (collectively, the + "License"). You may not use this file except in compliance with the + License. You can obtain a copy of the License at + http://gephi.org/about/legal/license-notice/ + or /cddl-1.0.txt and /gpl-3.0.txt. See the License for the + specific language governing permissions and limitations under the + License. When distributing the software, include this License Header + Notice in each file and include the License files at + /cddl-1.0.txt and /gpl-3.0.txt. If applicable, add the following below the + License Header, with the fields enclosed by brackets [] replaced by + your own identifying information: + "Portions Copyrighted [year] [name of copyright owner]" + + If you wish your version of this file to be governed by only the CDDL + or only the GPL Version 3, indicate your decision by adding + "[Contributor] elects to include this software in this distribution + under the [CDDL or GPL Version 3] license." If you do not indicate a + single choice of license, a recipient has the option to distribute + your version of this file under either the CDDL, the GPL Version 3 or + to extend the choice of license to its licensees as provided above. + However, if you add GPL Version 3 code and therefore, elected the GPL + Version 3 license, then the option applies only if the new code is + made subject to such option by the copyright holder. + + Contributor(s): + + Portions Copyrighted 2011 Gephi Consortium. + */ +package org.gephi.project.spi; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import org.gephi.project.api.Workspace; + +/** + * + * @author mbastian + */ +public interface WorkspaceBytesPersistenceProvider { + + /** + *

This is automatically called when saving a project file.

+ *

Your implementation must enclose all your data xml in a tag with the + * name provided in your + * getIdentifier method.

+ * + * @param writer XMLStreamWriter for xml serialization of this persistence + * provider data + * @param workspace Current workspace being serialized + */ + public void writeBytes(DataOutputStream stream, Workspace workspace); + + /** + *

This is automatically called when a start element with the tag name + * provided in your + * getIdentifier method.

+ *

Your implementation must detect the tag end element to stop + * reading.

+ * + * @param reader XMLStreamReader for deserialization of this persistence + * provider data previously serialized + * @param workspace Current workspace being deserialized + */ + public void readBytes(DataInputStream stream, Workspace workspace); + + /** + * Unique XML tag identifier for your + * WorkspacePersistenceProvider + * + * @return Unique identifier describing your data + */ + public String getIdentifier(); +} -- GitLab