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