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