--- /dev/null
+package org.simantics.export.core.manager;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Collections;\r
+import java.util.Comparator;\r
+import java.util.HashMap;\r
+import java.util.HashSet;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.Set;\r
+import java.util.regex.Matcher;\r
+import java.util.regex.Pattern;\r
+\r
+import org.simantics.databoard.Accessors;\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.databoard.accessor.RecordAccessor;\r
+import org.simantics.databoard.accessor.error.AccessorConstructionException;\r
+import org.simantics.databoard.accessor.error.AccessorException;\r
+import org.simantics.databoard.accessor.reference.LabelReference;\r
+import org.simantics.databoard.binding.error.BindingException;\r
+import org.simantics.databoard.binding.mutable.Variant;\r
+import org.simantics.databoard.type.RecordType;\r
+import org.simantics.export.core.ExportContext;\r
+import org.simantics.export.core.error.ExportException;\r
+import org.simantics.export.core.intf.Format;\r
+import org.simantics.export.core.intf.Publisher;\r
+import org.simantics.export.core.util.ExporterUtils;\r
+\r
+/**\r
+ * Result of an export wizard.\r
+ *\r
+ * @author toni.kalajainen@semantum.fi\r
+ */\r
+public class ExportWizardResult {\r
+ \r
+ public static LabelReference P_OUTPUT_OPTIONS = new LabelReference("Output Options"); \r
+ public static final Pattern PATTR = Pattern.compile("url=(.*),formatId=(.*)");\r
+ \r
+ public RecordType type;\r
+ public RecordAccessor accessor;\r
+ public Variant options;\r
+ public List<Content> contents; \r
+ public String publisherId; \r
+ \r
+ /**\r
+ * Create an action plan of this wizard result.\r
+ * \r
+ * @param ctx\r
+ * @param plan\r
+ * @throws ExportException if plan could noe be generated\r
+ */\r
+ public void createPlan( ExportContext ctx, ExportPlan plan ) \r
+ throws ExportException\r
+ {\r
+ // The publish manifest\r
+ List<Content> manifest = new ArrayList<Content>();\r
+ // Action lists. 1. for attachment creation, 2. containers \r
+ List<ExportAction> actions = new ArrayList<ExportAction>();\r
+ \r
+ // Add action that asserts or creates that publish location exists\r
+ Publisher publisher = ctx.eep.getPublisher( publisherId );\r
+ Variant locationOptions = ExporterUtils.getPublisherLocationOptions(ctx, publisherId, options);\r
+ boolean locationExists = publisher.publisherClass().locationExists(ctx, locationOptions);\r
+ if ( !locationExists ) {\r
+ CreatePublishLocationAction assertLocationAction = new CreatePublishLocationAction(publisher.id());\r
+ actions.add(assertLocationAction);\r
+ }\r
+ \r
+ // Create export actions and manifest\r
+ createExportActions(ctx, actions, manifest);\r
+\r
+ // Add Publish action\r
+ PublishAction pa = new PublishAction(publisher.id(), locationOptions, manifest);\r
+ actions.add( pa );\r
+ \r
+ plan.actions.addAll( actions );\r
+ plan.manifest.addAll( manifest );\r
+ }\r
+\r
+ /**\r
+ * Create export actions and manifest \r
+ * @param ctx\r
+ * @param actions\r
+ * @param manifest\r
+ * @throws ExportException \r
+ */\r
+ public void createExportActions(ExportContext ctx, List<ExportAction> actions, List<Content> manifest) throws ExportException \r
+ {\r
+ Comparator<Content> exportPriorityComparator = ExporterUtils.createExportPriorityComparator( ctx.eep );\r
+ // Add plan one model at a time.\r
+ for (String modelId : listModels( contents )) {\r
+ // Get contents of this model\r
+ List<Content> modelCts = filterByModel( contents, modelId );\r
+ // Content -> ExportAction\r
+ Map<Content, ExportAction> contentActionMap = new HashMap<Content, ExportAction>();\r
+ Collections.sort(modelCts, exportPriorityComparator);\r
+ // Model Name\r
+ String modelName = modelId.substring( modelId.lastIndexOf('/')+1 );\r
+ \r
+ // Create non-merged, non-group content (diagram)\r
+ for ( Content content : modelCts ) {\r
+ if ( mergeFormat(content.formatExt) ) continue;\r
+ Format format = ctx.eep.getFormat( content.formatId ); \r
+ if ( format.isGroupFormat() || format.isContainerFormat() ) continue;\r
+ \r
+ ExportSingleContent action = new ExportSingleContent( content );\r
+ action.contentTypeId = content.contentTypeId;\r
+ action.contentUri = content.url;\r
+ action.formatId = content.formatId;\r
+ actions.add( action );\r
+ contentActionMap.put( content, action );\r
+ manifest.add( content );\r
+ }\r
+\r
+ // Create non-merged, group content (chart.csv, subscription.csv)\r
+ for ( Content content : modelCts ) {\r
+ if ( mergeFormat(content.formatExt) ) continue;\r
+ Format format = ctx.eep.getFormat( content.formatId ); \r
+ if ( !format.isGroupFormat() || format.isContainerFormat() || format.isLinkContainer() ) continue;\r
+\r
+ ExportGroupCreateAction action = new ExportGroupCreateAction( content, format.id() );\r
+ \r
+ action.addContent(content, null);\r
+ actions.add( action ); \r
+ contentActionMap.put( content, action );\r
+ manifest.add( content );\r
+ }\r
+\r
+ // Create merged, group content (model.csv)\r
+ for ( Format format : ctx.eep.formats() ) {\r
+ if ( !mergeFormat(format.fileext()) ) continue;\r
+ if ( !format.isGroupFormat() || format.isContainerFormat() || format.isLinkContainer()) continue;\r
+ Content groupContent = new Content( modelId, null, format.id(), modelName, format.fileext(), modelId ); \r
+ ExportGroupCreateAction action = new ExportGroupCreateAction( groupContent, format.id() );\r
+ for ( Content c : filterByFormat(modelCts, format.id()) ) {\r
+ \r
+ action.addContent(c, null);\r
+ \r
+ // These actions are grouped. Do not export them explicitely\r
+ ExportAction contentsAction = contentActionMap.get(c);\r
+ contentActionMap.remove( c );\r
+ actions.remove(contentsAction);\r
+ modelCts.remove( c );\r
+ }\r
+ actions.add( action ); \r
+ contentActionMap.put( groupContent, action );\r
+ manifest.add( groupContent );\r
+ }\r
+\r
+ // Create non-merged, container content (diagram.pdf, chart.pdf)\r
+ for ( Content content : modelCts ) {\r
+ if ( mergeFormat(content.formatExt) ) continue;\r
+ Format format = ctx.eep.getFormat( content.formatId );\r
+ if ( !format.isContainerFormat() || format.isLinkContainer() ) continue;\r
+ \r
+ boolean includeAttachments = includeAttachments( format.fileext() );\r
+ boolean exportAttachments = exportAttachments( format.fileext() );\r
+ \r
+ ExportGroupCreateAction action = new ExportGroupCreateAction( content, format.id() );\r
+ List<Content> attachmentsCts = new ArrayList<Content>(); \r
+ if ( includeAttachments ) attachmentsCts = filterByUrl(modelCts, content.url);\r
+ attachmentsCts = filterAllAttachable(ctx, attachmentsCts);\r
+ attachmentsCts.remove( content );\r
+ action.addContent( content, attachmentsCts );\r
+ actions.add( action );\r
+ contentActionMap.put( content, action );\r
+ manifest.add( content );\r
+ \r
+ if ( !exportAttachments ) {\r
+ attachmentsCts = filterNotIsAlwaysPublished(ctx, attachmentsCts);\r
+ manifest.removeAll( attachmentsCts );\r
+ }\r
+ \r
+ } \r
+ \r
+ // Create merged, container content (model.pdf)\r
+ for ( Format format : ctx.eep.formats() ) {\r
+ if ( !mergeFormat(format.fileext()) ) continue;\r
+ if ( !format.isContainerFormat() || format.isLinkContainer() ) continue;\r
+ Content groupContent = new Content( modelId, null, format.id(), modelName, format.fileext(), modelId ); \r
+ ExportGroupCreateAction action = new ExportGroupCreateAction( groupContent, format.id() );\r
+\r
+ boolean includeAttachments = includeAttachments( format.fileext() );\r
+ boolean exportAttachments = exportAttachments( format.fileext() );\r
+ \r
+ // Add pages and page attachments\r
+ List<Content> remainingCts = new ArrayList<Content>( contentActionMap.keySet() );\r
+ List<Content> pages = filterByFormat(modelCts, format.id());\r
+ remainingCts.remove( pages );\r
+ for ( Content page : pages ) {\r
+ List<Content> pageAttachments = new ArrayList<Content>();\r
+ if ( includeAttachments || exportAttachments ) { \r
+ pageAttachments = filterByUrl(modelCts, page.url);\r
+ pageAttachments = filterAllAttachable(ctx, pageAttachments);\r
+ pageAttachments.remove(page);\r
+ remainingCts.removeAll( pageAttachments );\r
+ }\r
+ action.addContent(page, includeAttachments ? pageAttachments : null );\r
+ }\r
+ \r
+ // Add rest of the attachments\r
+ if ( includeAttachments ) action.addContent(null, remainingCts); \r
+ \r
+ if ( !exportAttachments ) {\r
+ \r
+ List<Content> attachmentsCts = filterNotIsAlwaysPublished(ctx, action.getAttachments());\r
+ manifest.removeAll( attachmentsCts );\r
+ \r
+ }\r
+ \r
+ actions.add( action );\r
+ manifest.add( groupContent );\r
+ }\r
+ \r
+ \r
+ // Create non-merged, link container (diagram.xml)\r
+ Set<Content> unlinkedContent = new HashSet<Content>( manifest );\r
+ ExportGroupCreateAction mainLinkAction = null;\r
+ for ( Content content : modelCts ) {\r
+ if ( mergeFormat(content.formatExt) ) continue;\r
+ Format format = ctx.eep.getFormat( content.formatId ); \r
+ if ( !format.isLinkContainer() ) continue;\r
+\r
+ ExportGroupCreateAction action = new ExportGroupCreateAction( content, format.id() ); \r
+ List<Content> attachmentsCts = new ArrayList<Content>(); \r
+ if ( format.isLinkContainer() ) {\r
+ attachmentsCts = filterByUrl(manifest, content.url);\r
+ attachmentsCts.remove( content );\r
+ }\r
+ \r
+ action.addContent(content, attachmentsCts);\r
+ unlinkedContent.removeAll(attachmentsCts);\r
+ actions.add( action ); \r
+ contentActionMap.put( content, action );\r
+ manifest.add( content );\r
+ if ( mainLinkAction == null ) mainLinkAction = action; \r
+ }\r
+\r
+ // Create merged, link container (model.xml)\r
+ for ( Format format : ctx.eep.formats() ) {\r
+ if ( !mergeFormat(format.fileext()) ) continue;\r
+ if ( !format.isLinkContainer() ) continue;\r
+ \r
+ Content groupContent = new Content( modelId, null, format.id(), modelName, format.fileext(), modelId ); \r
+ ExportGroupCreateAction action = new ExportGroupCreateAction( groupContent, format.id() );\r
+ for ( Content c : filterByFormat(modelCts, format.id()) ) {\r
+ \r
+ List<Content> attachmentsCts = new ArrayList<Content>(); \r
+ if ( format.isLinkContainer() ) {\r
+ attachmentsCts = filterByUrl(manifest, c.url);\r
+ attachmentsCts.remove( groupContent );\r
+ }\r
+ action.addContent(c, attachmentsCts);\r
+ unlinkedContent.removeAll(attachmentsCts);\r
+ \r
+ // These actions are grouped. Do not export them explicitely\r
+ ExportAction contentsAction = contentActionMap.get(c);\r
+ contentActionMap.remove( c );\r
+ actions.remove(contentsAction);\r
+ modelCts.remove( c );\r
+ }\r
+ mainLinkAction = action;\r
+ actions.add( action ); \r
+ contentActionMap.put( groupContent, action );\r
+ manifest.add( groupContent );\r
+ }\r
+ \r
+ // Link all that were not linked to somewhere.\r
+ if ( mainLinkAction!=null && !unlinkedContent.isEmpty() && !mainLinkAction.contents.isEmpty() ) {\r
+ mainLinkAction.attachments.addAll(mainLinkAction.contents.get(0), unlinkedContent);\r
+ }\r
+ \r
+ } \r
+ }\r
+ \r
+ @Override\r
+ public String toString() {\r
+ StringBuilder sb = new StringBuilder();\r
+ sb.append( "Export Wizard Result:\n" );\r
+ try {\r
+ sb.append( " Options: "+options.getBinding().toString(options.getValue(), true)+"\n");\r
+ } catch (BindingException e) {\r
+ sb.append( " Options: "+e.getMessage()+"\n");\r
+ }\r
+ sb.append( " Content: \n");\r
+ for ( Content c : contents ) {\r
+ sb.append( " "+c.url+", formatId="+c.formatId+", contentType="+c.contentTypeId ); \r
+ }\r
+ return sb.toString();\r
+ }\r
+ \r
+ public static Set<Content> parse(String str) {\r
+ HashSet<Content> result = new HashSet<Content>();\r
+ \r
+ for (String s : str.split(";")) {\r
+ Matcher m = PATTR.matcher(s);\r
+ if ( m.matches() ) {\r
+ String url = m.group(1);\r
+ String formatId = m.group(2);\r
+ Content c = new Content(url, null, formatId, null, null, null);\r
+ result.add( c );\r
+ }\r
+ }\r
+ \r
+ return result;\r
+ }\r
+ \r
+ public static String print(Collection<Content> cnts) {\r
+ if ( cnts==null ) return "";\r
+ StringBuilder sb = new StringBuilder();\r
+ for (Content c : cnts) {\r
+ if ( sb.length()>0 ) sb.append(";");\r
+ sb.append( c.toString() );\r
+ }\r
+ return sb.toString();\r
+ }\r
+\r
+ boolean mergeFormat(String formatExt) {\r
+ try {\r
+ RecordAccessor ra = Accessors.getAccessor(options);\r
+ RecordAccessor rao = ra.getComponent(P_OUTPUT_OPTIONS);\r
+ Boolean b = (Boolean) rao.getValue(new LabelReference("Merge "+formatExt+" content into one file"), Bindings.BOOLEAN);\r
+ return b!=null && b;\r
+ } catch (AccessorConstructionException e) {\r
+ return false;\r
+ } catch (AccessorException e) {\r
+ return false;\r
+ }\r
+ }\r
+ \r
+ boolean includeAttachments(String formatExt) {\r
+ try {\r
+ RecordAccessor ra = Accessors.getAccessor(options);\r
+ RecordAccessor rao = ra.getComponent(P_OUTPUT_OPTIONS);\r
+ Boolean b = (Boolean) rao.getValue(new LabelReference("Include attachments to "+formatExt), Bindings.BOOLEAN);\r
+ return b!=null && b;\r
+ } catch (AccessorConstructionException e) {\r
+ return false;\r
+ } catch (AccessorException e) {\r
+ return false;\r
+ }\r
+ }\r
+ \r
+ boolean exportAttachments(String formatExt) {\r
+ try {\r
+ RecordAccessor ra = Accessors.getAccessor(options);\r
+ RecordAccessor rao = ra.getComponent(P_OUTPUT_OPTIONS);\r
+ Boolean b = (Boolean) rao.getValue(new LabelReference("Export attachments of "+formatExt+" to separate files"), Bindings.BOOLEAN);\r
+ return b!=null && b;\r
+ } catch (AccessorConstructionException e) {\r
+ return false;\r
+ } catch (AccessorException e) {\r
+ return false;\r
+ }\r
+ }\r
+ \r
+ List<Content> filterByFormat(Collection<Content> contents, String formatId) {\r
+ ArrayList<Content> result = new ArrayList<Content>();\r
+ for ( Content c : contents ) if ( c.formatId.equals(formatId) ) result.add( c );\r
+ return result;\r
+ }\r
+ \r
+ List<Content> filterByModel(Collection<Content> contents, String modelId) {\r
+ ArrayList<Content> result = new ArrayList<Content>();\r
+ for ( Content c : contents ) if ( c.modelId.equals(modelId) ) result.add( c );\r
+ return result;\r
+ }\r
+\r
+ List<Content> filterByUrl(Collection<Content> contents, String contentUrl) {\r
+ ArrayList<Content> result = new ArrayList<Content>();\r
+ for ( Content c : contents ) if ( c.url.equals(contentUrl) ) result.add( c );\r
+ return result;\r
+ }\r
+ \r
+ List<Content> filterAllAttachable(ExportContext ctx, Collection<Content> contents) {\r
+ ArrayList<Content> result = new ArrayList<Content>();\r
+ for ( Content c : contents ) {\r
+ Format cf = ctx.eep.getFormat( c.formatId );\r
+ if ( cf.isAttachable() ) result.add( c );\r
+ }\r
+ return result;\r
+ }\r
+ \r
+ List<Content> filterNotIsAlwaysPublished(ExportContext ctx, Collection<Content> contents) {\r
+ ArrayList<Content> result = new ArrayList<Content>();\r
+ for ( Content c : contents ) {\r
+ Format cf = ctx.eep.getFormat( c.formatId );\r
+ if ( !cf.isAlwaysPublished() ) result.add( c );\r
+ }\r
+ return result;\r
+ }\r
+ \r
+ \r
+ List<String> listModels(Collection<Content> contents) {\r
+ ArrayList<String> result = new ArrayList<String>();\r
+ for ( Content c : contents ) if ( !result.contains(c.modelId) ) result.add( c.modelId );\r
+ return result;\r
+ }\r
+ \r
+ \r
+}\r