]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.export.core/src/org/simantics/export/core/manager/ExportGroupCreateAction.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.export.core / src / org / simantics / export / core / manager / ExportGroupCreateAction.java
diff --git a/bundles/org.simantics.export.core/src/org/simantics/export/core/manager/ExportGroupCreateAction.java b/bundles/org.simantics.export.core/src/org/simantics/export/core/manager/ExportGroupCreateAction.java
new file mode 100644 (file)
index 0000000..8f612f9
--- /dev/null
@@ -0,0 +1,215 @@
+package org.simantics.export.core.manager;\r
+\r
+import java.io.File;\r
+import java.io.IOException;\r
+import java.util.ArrayList;\r
+import java.util.Arrays;\r
+import java.util.Collections;\r
+import java.util.Comparator;\r
+import java.util.List;\r
+\r
+import org.eclipse.core.runtime.IProgressMonitor;\r
+import org.eclipse.core.runtime.OperationCanceledException;\r
+import org.eclipse.core.runtime.SubMonitor;\r
+import org.simantics.Simantics;\r
+import org.simantics.databoard.binding.mutable.Variant;\r
+import org.simantics.databoard.util.URIUtil;\r
+import org.simantics.export.core.ExportContext;\r
+import org.simantics.export.core.error.ExportException;\r
+import org.simantics.export.core.intf.Exporter;\r
+import org.simantics.export.core.intf.Format;\r
+import org.simantics.export.core.util.ExporterUtils;\r
+import org.simantics.utils.datastructures.MapList;\r
+import org.simantics.utils.strings.AlphanumComparator;\r
+\r
+/**\r
+ * This action exports similar content types into one file of group format (e.g. Pdf, CSV).\r
+ * Group format is a file that can carry multiple items of one content type.  \r
+ *\r
+ * @author toni.kalajainen@semantum.fi\r
+ */\r
+public class ExportGroupCreateAction extends ExportAction {\r
+\r
+       // Contents and attachments\r
+       public Content dstContent;\r
+       public List<Content> contents = new ArrayList<Content>();\r
+       // All attachments. Note, there are also attachments for the key: null\r
+       public MapList<Content, Content> attachments = new MapList<Content, Content>();\r
+       public String formatId;\r
+       public File outputFile;\r
+\r
+       public ExportGroupCreateAction(Content dstContent, String formatId) \r
+       {\r
+               this.dstContent = dstContent;\r
+               this.formatId = formatId;\r
+       }\r
+\r
+       public void addContent(Content srcContent, List<Content> attachments) {\r
+               if ( srcContent != null ) contents.add(srcContent);\r
+               if (attachments!=null) this.attachments.addAll(srcContent, attachments);\r
+       }\r
+\r
+       public void execute(ExportContext ctx, IProgressMonitor monitor, Variant options) throws ExportException\r
+       {\r
+               Format format = ctx.eep.getFormat( formatId );\r
+\r
+               // Sort content to exporter, and create the exporters\r
+               MapList<List<Exporter>, Content> map = new MapList<List<Exporter>, Content>();\r
+               for ( Content content : contents ) {\r
+                       Exporter[] exporters = ctx.eep.getExporters(content.formatId, content.contentTypeId);\r
+                       if ( exporters.length == 0 ) {\r
+                               throw new ExportException("No suitable exporter found for exporting "+content.contentTypeId+" to a "+format.label());\r
+                       }\r
+                       map.add(Arrays.asList(exporters), content);\r
+               }\r
+\r
+               try {\r
+                       // Prefix must be at least 3 characters in length\r
+                       String prefix = "___" + URIUtil.encodeFilename(dstContent.label);\r
+                       dstContent.tmpFile = outputFile = File.createTempFile( prefix, URIUtil.encodeFilename(format.fileext()), Simantics.getTemporaryDirectory("export.core") );\r
+               } catch (IOException e) {\r
+                       throw new ExportException(e);\r
+               }\r
+\r
+               // Calculate amount of total work from the amount of exporters and contents.\r
+               int totalWork = 0;\r
+               final int singleExportWork = 10000;\r
+               for (List<Exporter> exporters : map.getKeys()) {\r
+                       List<Content> contents = map.getValuesUnsafe( exporters );\r
+                       totalWork += (contents.size() * exporters.size() + 1) * singleExportWork;\r
+               }\r
+\r
+               SubMonitor mon = SubMonitor.convert(monitor, totalWork);\r
+\r
+               Object writer = format.createFile(ctx, outputFile, options);\r
+               try {\r
+                       // Sort exporters based on content type id to give a deterministic order\r
+                       // for List<Exporter> -> List<Content> iteration.\r
+                       List<List<Exporter>> sortedKeys = new ArrayList<List<Exporter>>( map.getKeys() );\r
+                       Collections.sort(sortedKeys, EXPORTER_LIST_COMPARATOR);\r
+                       //System.out.println("sorted keys:\n" + EString.implode(sortedKeys));\r
+\r
+                       // Write pages, exporter at a time.\r
+                       for ( List<Exporter> exporters : sortedKeys ) {\r
+                               //System.out.println("exporters:\n" + EString.implode(exporters));\r
+                               List<Content> contents = map.getValues( exporters );\r
+                               List<Content> sortedContent = ExporterUtils.sortedContent( contents );\r
+                               for (Content content : sortedContent) {\r
+                                       //System.out.println("content: " + content);\r
+                                       for ( Exporter exporter : exporters ) {\r
+                                               if (monitor.isCanceled())\r
+                                                       throw new OperationCanceledException();\r
+\r
+                                               //System.out.println("exporter: " + exporter);\r
+                                               mon.subTask( exporter.formatId() + ": " + content.label);\r
+                                               exporter.exportAction().export(\r
+                                                               Collections.singletonList(content),\r
+                                                               writer, \r
+                                                               ctx, \r
+                                                               options,\r
+                                                               mon.newChild(singleExportWork),\r
+                                                               attachments);\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       // Write attachments\r
+                       List<Content> remainingAttachments = attachments.getValues(null);\r
+                       if ( remainingAttachments!=null && !remainingAttachments.isEmpty() ) {\r
+                               format.addAttachment(ctx, writer, remainingAttachments);\r
+                       }\r
+\r
+                       // Remember the output file (This is for the publisher)\r
+                       dstContent.tmpFile = outputFile;\r
+\r
+               } catch (ExportException ee) {\r
+                       if ( outputFile.exists() ) outputFile.delete();\r
+                       throw ee;\r
+               } finally {\r
+                       if (writer!=null) {\r
+                               // TODO: pass progress monitor to closeFile since closeFile may do a lot of work in some cases\r
+                               format.closeFile( ctx, writer );\r
+                               mon.worked(singleExportWork);\r
+                               writer = null;\r
+                       }\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Required for sorting the PDF output into a deterministic order.\r
+        */\r
+       Comparator<List<Exporter>> EXPORTER_LIST_COMPARATOR = new Comparator<List<Exporter>>() {\r
+               String repr(List<Exporter> l) {\r
+                       for (Exporter e : l)\r
+                               return e.contentTypeId();\r
+                       throw new IllegalArgumentException("empty exporter list");\r
+               }\r
+               @Override\r
+               public int compare(List<Exporter> o1, List<Exporter> o2) {\r
+                       String k1 = repr(o1);\r
+                       String k2 = repr(o2);\r
+                       return AlphanumComparator.CASE_INSENSITIVE_COMPARATOR.compare(k1, k2);\r
+               }\r
+       };\r
+\r
+       @Override\r
+       public String label(ExportContext ctx) {\r
+               String label;\r
+               Format format = ctx.eep.getFormat( formatId );\r
+               if ( contents.size()==1 ) {\r
+                       label = contents.iterator().next().label;\r
+               } else {\r
+                       label = "Writing "+contents.size()+" items to a "+format.label()+" file";\r
+               }\r
+               if ( outputFile == null ) return label;\r
+               return label + " export to "+outputFile.getName();\r
+       }\r
+\r
+       @Override\r
+       public int work(ExportContext ctx) {\r
+               return contents.size() + 1;\r
+       }\r
+\r
+       @Override\r
+       public List<String> validate(ExportContext ctx, Variant options) {\r
+               List<String> result = new ArrayList<String>(0);\r
+\r
+               for (Content content : contents) {\r
+\r
+                       Exporter[] exporters = ctx.eep.getExporters(formatId, content.contentTypeId);\r
+                       if ( exporters.length == 0 ) {\r
+                               result.add("Could not find exporter for "+content.filename);\r
+                               continue;\r
+                       }\r
+\r
+                       for ( Exporter exporter : exporters) {\r
+                               try {\r
+                                       result.addAll( exporter.exportAction().validate(content.url, ctx, options) );\r
+                               } catch (ExportException e) {\r
+                                       result.add( e.getClass().getName()+": "+e.getMessage() );\r
+                               }\r
+                       }\r
+               }\r
+\r
+               return result;\r
+       }\r
+\r
+       @Override\r
+       public void cleanup(ExportContext ctx, IProgressMonitor progress, Variant options) throws ExportException {\r
+               if ( this.outputFile != null ) { \r
+                       this.outputFile.delete();\r
+                       dstContent.tmpFile = null;\r
+               }\r
+       }\r
+\r
+       public List<Content> getAttachments() {\r
+               List<Content> result = new ArrayList<Content>();\r
+               for ( Content key : attachments.getKeys() ) {\r
+                       for ( Content value : attachments.getValuesUnsafe(key) ) {\r
+                               if ( !result.contains(value) ) result.add(value);\r
+                       }\r
+               }               \r
+               return result;\r
+       }\r
+\r
+}\r