1 package org.simantics.export.core.manager;
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.Collections;
6 import java.util.Comparator;
7 import java.util.HashMap;
8 import java.util.HashSet;
12 import java.util.regex.Matcher;
13 import java.util.regex.Pattern;
15 import org.simantics.databoard.Accessors;
16 import org.simantics.databoard.Bindings;
17 import org.simantics.databoard.accessor.RecordAccessor;
18 import org.simantics.databoard.accessor.error.AccessorConstructionException;
19 import org.simantics.databoard.accessor.error.AccessorException;
20 import org.simantics.databoard.accessor.reference.LabelReference;
21 import org.simantics.databoard.binding.error.BindingException;
22 import org.simantics.databoard.binding.mutable.Variant;
23 import org.simantics.databoard.type.RecordType;
24 import org.simantics.export.core.ExportContext;
25 import org.simantics.export.core.error.ExportException;
26 import org.simantics.export.core.intf.Format;
27 import org.simantics.export.core.intf.Publisher;
28 import org.simantics.export.core.util.ExporterUtils;
31 * Result of an export wizard.
33 * @author toni.kalajainen@semantum.fi
35 public class ExportWizardResult {
37 public static LabelReference P_OUTPUT_OPTIONS = new LabelReference("Output Options");
38 public static final Pattern PATTR = Pattern.compile("url=(.*),formatId=(.*)");
40 public RecordType type;
41 public RecordAccessor accessor;
42 public Variant options;
43 public List<Content> contents;
44 public String publisherId;
47 * Create an action plan of this wizard result.
51 * @throws ExportException if plan could noe be generated
53 public void createPlan( ExportContext ctx, ExportPlan plan )
54 throws ExportException
56 // The publish manifest
57 List<Content> manifest = new ArrayList<Content>();
58 // Action lists. 1. for attachment creation, 2. containers
59 List<ExportAction> actions = new ArrayList<ExportAction>();
61 // Add action that asserts or creates that publish location exists
62 Publisher publisher = ctx.eep.getPublisher( publisherId );
63 Variant locationOptions = ExporterUtils.getPublisherLocationOptions(ctx, publisherId, options);
64 boolean locationExists = publisher.publisherClass().locationExists(ctx, locationOptions);
65 if ( !locationExists ) {
66 CreatePublishLocationAction assertLocationAction = new CreatePublishLocationAction(publisher.id());
67 actions.add(assertLocationAction);
70 // Create export actions and manifest
71 createExportActions(ctx, actions, manifest);
74 PublishAction pa = new PublishAction(publisher.id(), locationOptions, manifest);
77 plan.actions.addAll( actions );
78 plan.manifest.addAll( manifest );
82 * Create export actions and manifest
86 * @throws ExportException
88 public void createExportActions(ExportContext ctx, List<ExportAction> actions, List<Content> manifest) throws ExportException
90 Comparator<Content> exportPriorityComparator = ExporterUtils.createExportPriorityComparator( ctx.eep );
91 // Add plan one model at a time.
92 for (String modelId : listModels( contents )) {
93 // Get contents of this model
94 List<Content> modelCts = filterByModel( contents, modelId );
95 // Content -> ExportAction
96 Map<Content, ExportAction> contentActionMap = new HashMap<Content, ExportAction>();
97 Collections.sort(modelCts, exportPriorityComparator);
99 String modelName = modelId.substring( modelId.lastIndexOf('/')+1 );
101 // Create non-merged, non-group content (diagram)
102 for ( Content content : modelCts ) {
103 if ( mergeFormat(content.formatExt) ) continue;
104 Format format = ctx.eep.getFormat( content.formatId );
105 if ( format.isGroupFormat() || format.isContainerFormat() ) continue;
107 ExportSingleContent action = new ExportSingleContent( content );
108 action.contentTypeId = content.contentTypeId;
109 action.contentUri = content.url;
110 action.formatId = content.formatId;
111 actions.add( action );
112 contentActionMap.put( content, action );
113 manifest.add( content );
116 // Create non-merged, group content (chart.csv, subscription.csv)
117 for ( Content content : modelCts ) {
118 if ( mergeFormat(content.formatExt) ) continue;
119 Format format = ctx.eep.getFormat( content.formatId );
120 if ( !format.isGroupFormat() || format.isContainerFormat() || format.isLinkContainer() ) continue;
122 ExportGroupCreateAction action = new ExportGroupCreateAction( content, format.id() );
124 action.addContent(content, null);
125 actions.add( action );
126 contentActionMap.put( content, action );
127 manifest.add( content );
130 // Create merged, group content (model.csv)
131 for ( Format format : ctx.eep.formats() ) {
132 if ( !mergeFormat(format.fileext()) ) continue;
133 if ( !format.isGroupFormat() || format.isContainerFormat() || format.isLinkContainer()) continue;
134 Content groupContent = new Content( modelId, null, format.id(), modelName, format.fileext(), modelId );
135 ExportGroupCreateAction action = new ExportGroupCreateAction( groupContent, format.id() );
136 for ( Content c : filterByFormat(modelCts, format.id()) ) {
138 action.addContent(c, null);
140 // These actions are grouped. Do not export them explicitely
141 ExportAction contentsAction = contentActionMap.get(c);
142 contentActionMap.remove( c );
143 actions.remove(contentsAction);
144 modelCts.remove( c );
146 actions.add( action );
147 contentActionMap.put( groupContent, action );
148 manifest.add( groupContent );
151 // Create non-merged, container content (diagram.pdf, chart.pdf)
152 for ( Content content : modelCts ) {
153 if ( mergeFormat(content.formatExt) ) continue;
154 Format format = ctx.eep.getFormat( content.formatId );
155 if ( !format.isContainerFormat() || format.isLinkContainer() ) continue;
157 boolean includeAttachments = includeAttachments( format.fileext() );
158 boolean exportAttachments = exportAttachments( format.fileext() );
160 ExportGroupCreateAction action = new ExportGroupCreateAction( content, format.id() );
161 List<Content> attachmentsCts = new ArrayList<Content>();
162 if ( includeAttachments ) attachmentsCts = filterByUrl(modelCts, content.url);
163 attachmentsCts = filterAllAttachable(ctx, attachmentsCts);
164 attachmentsCts.remove( content );
165 action.addContent( content, attachmentsCts );
166 actions.add( action );
167 contentActionMap.put( content, action );
168 manifest.add( content );
170 if ( !exportAttachments ) {
171 attachmentsCts = filterNotIsAlwaysPublished(ctx, attachmentsCts);
172 manifest.removeAll( attachmentsCts );
177 // Create merged, container content (model.pdf)
178 for ( Format format : ctx.eep.formats() ) {
179 if ( !mergeFormat(format.fileext()) ) continue;
180 if ( !format.isContainerFormat() || format.isLinkContainer() ) continue;
181 Content groupContent = new Content( modelId, null, format.id(), modelName, format.fileext(), modelId );
182 ExportGroupCreateAction action = new ExportGroupCreateAction( groupContent, format.id() );
184 boolean includeAttachments = includeAttachments( format.fileext() );
185 boolean exportAttachments = exportAttachments( format.fileext() );
187 // Add pages and page attachments
188 List<Content> remainingCts = new ArrayList<Content>( contentActionMap.keySet() );
189 List<Content> pages = filterByFormat(modelCts, format.id());
190 remainingCts.remove( pages );
191 for ( Content page : pages ) {
192 List<Content> pageAttachments = new ArrayList<Content>();
193 if ( includeAttachments || exportAttachments ) {
194 pageAttachments = filterByUrl(modelCts, page.url);
195 pageAttachments = filterAllAttachable(ctx, pageAttachments);
196 pageAttachments.remove(page);
197 remainingCts.removeAll( pageAttachments );
199 action.addContent(page, includeAttachments ? pageAttachments : null );
202 // Add rest of the attachments
203 if ( includeAttachments ) action.addContent(null, remainingCts);
205 if ( !exportAttachments ) {
207 List<Content> attachmentsCts = filterNotIsAlwaysPublished(ctx, action.getAttachments());
208 manifest.removeAll( attachmentsCts );
212 actions.add( action );
213 manifest.add( groupContent );
217 // Create non-merged, link container (diagram.xml)
218 Set<Content> unlinkedContent = new HashSet<Content>( manifest );
219 ExportGroupCreateAction mainLinkAction = null;
220 for ( Content content : modelCts ) {
221 if ( mergeFormat(content.formatExt) ) continue;
222 Format format = ctx.eep.getFormat( content.formatId );
223 if ( !format.isLinkContainer() ) continue;
225 ExportGroupCreateAction action = new ExportGroupCreateAction( content, format.id() );
226 List<Content> attachmentsCts = new ArrayList<Content>();
227 if ( format.isLinkContainer() ) {
228 attachmentsCts = filterByUrl(manifest, content.url);
229 attachmentsCts.remove( content );
232 action.addContent(content, attachmentsCts);
233 unlinkedContent.removeAll(attachmentsCts);
234 actions.add( action );
235 contentActionMap.put( content, action );
236 manifest.add( content );
237 if ( mainLinkAction == null ) mainLinkAction = action;
240 // Create merged, link container (model.xml)
241 for ( Format format : ctx.eep.formats() ) {
242 if ( !mergeFormat(format.fileext()) ) continue;
243 if ( !format.isLinkContainer() ) continue;
245 Content groupContent = new Content( modelId, null, format.id(), modelName, format.fileext(), modelId );
246 ExportGroupCreateAction action = new ExportGroupCreateAction( groupContent, format.id() );
247 for ( Content c : filterByFormat(modelCts, format.id()) ) {
249 List<Content> attachmentsCts = new ArrayList<Content>();
250 if ( format.isLinkContainer() ) {
251 attachmentsCts = filterByUrl(manifest, c.url);
252 attachmentsCts.remove( groupContent );
254 action.addContent(c, attachmentsCts);
255 unlinkedContent.removeAll(attachmentsCts);
257 // These actions are grouped. Do not export them explicitely
258 ExportAction contentsAction = contentActionMap.get(c);
259 contentActionMap.remove( c );
260 actions.remove(contentsAction);
261 modelCts.remove( c );
263 mainLinkAction = action;
264 actions.add( action );
265 contentActionMap.put( groupContent, action );
266 manifest.add( groupContent );
269 // Link all that were not linked to somewhere.
270 if ( mainLinkAction!=null && !unlinkedContent.isEmpty() && !mainLinkAction.contents.isEmpty() ) {
271 mainLinkAction.attachments.addAll(mainLinkAction.contents.get(0), unlinkedContent);
278 public String toString() {
279 StringBuilder sb = new StringBuilder();
280 sb.append( "Export Wizard Result:\n" );
282 sb.append( " Options: "+options.getBinding().toString(options.getValue(), true)+"\n");
283 } catch (BindingException e) {
284 sb.append( " Options: "+e.getMessage()+"\n");
286 sb.append( " Content: \n");
287 for ( Content c : contents ) {
288 sb.append( " "+c.url+", formatId="+c.formatId+", contentType="+c.contentTypeId );
290 return sb.toString();
293 public static Set<Content> parse(String str) {
294 HashSet<Content> result = new HashSet<Content>();
296 for (String s : str.split(";")) {
297 Matcher m = PATTR.matcher(s);
299 String url = m.group(1);
300 String formatId = m.group(2);
301 Content c = new Content(url, null, formatId, null, null, null);
309 public static String print(Collection<Content> cnts) {
310 if ( cnts==null ) return "";
311 StringBuilder sb = new StringBuilder();
312 for (Content c : cnts) {
313 if ( sb.length()>0 ) sb.append(";");
314 sb.append( c.toString() );
316 return sb.toString();
319 boolean mergeFormat(String formatExt) {
321 RecordAccessor ra = Accessors.getAccessor(options);
322 RecordAccessor rao = ra.getComponent(P_OUTPUT_OPTIONS);
323 Boolean b = (Boolean) rao.getValue(new LabelReference("Merge "+formatExt+" content into one file"), Bindings.BOOLEAN);
325 } catch (AccessorConstructionException e) {
327 } catch (AccessorException e) {
332 boolean includeAttachments(String formatExt) {
334 RecordAccessor ra = Accessors.getAccessor(options);
335 RecordAccessor rao = ra.getComponent(P_OUTPUT_OPTIONS);
336 Boolean b = (Boolean) rao.getValue(new LabelReference("Include attachments to "+formatExt), Bindings.BOOLEAN);
338 } catch (AccessorConstructionException e) {
340 } catch (AccessorException e) {
345 boolean exportAttachments(String formatExt) {
347 RecordAccessor ra = Accessors.getAccessor(options);
348 RecordAccessor rao = ra.getComponent(P_OUTPUT_OPTIONS);
349 Boolean b = (Boolean) rao.getValue(new LabelReference("Export attachments of "+formatExt+" to separate files"), Bindings.BOOLEAN);
351 } catch (AccessorConstructionException e) {
353 } catch (AccessorException e) {
358 List<Content> filterByFormat(Collection<Content> contents, String formatId) {
359 ArrayList<Content> result = new ArrayList<Content>();
360 for ( Content c : contents ) if ( c.formatId.equals(formatId) ) result.add( c );
364 List<Content> filterByModel(Collection<Content> contents, String modelId) {
365 ArrayList<Content> result = new ArrayList<Content>();
366 for ( Content c : contents ) if ( c.modelId.equals(modelId) ) result.add( c );
370 List<Content> filterByUrl(Collection<Content> contents, String contentUrl) {
371 ArrayList<Content> result = new ArrayList<Content>();
372 for ( Content c : contents ) if ( c.url.equals(contentUrl) ) result.add( c );
376 List<Content> filterAllAttachable(ExportContext ctx, Collection<Content> contents) {
377 ArrayList<Content> result = new ArrayList<Content>();
378 for ( Content c : contents ) {
379 Format cf = ctx.eep.getFormat( c.formatId );
380 if ( cf.isAttachable() ) result.add( c );
385 List<Content> filterNotIsAlwaysPublished(ExportContext ctx, Collection<Content> contents) {
386 ArrayList<Content> result = new ArrayList<Content>();
387 for ( Content c : contents ) {
388 Format cf = ctx.eep.getFormat( c.formatId );
389 if ( !cf.isAlwaysPublished() ) result.add( c );
395 List<String> listModels(Collection<Content> contents) {
396 ArrayList<String> result = new ArrayList<String>();
397 for ( Content c : contents ) if ( !result.contains(c.modelId) ) result.add( c.modelId );