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