]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.export.ui/src/org/simantics/export/ui/OptionsPage.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.export.ui / src / org / simantics / export / ui / OptionsPage.java
1 package org.simantics.export.ui;\r
2 \r
3 import java.util.ArrayList;\r
4 import java.util.Collections;\r
5 import java.util.List;\r
6 import java.util.Map;\r
7 import java.util.Set;\r
8 import java.util.TreeMap;\r
9 import java.util.TreeSet;\r
10 import java.util.regex.Matcher;\r
11 import java.util.regex.Pattern;\r
12 \r
13 import org.eclipse.jface.wizard.WizardPage;\r
14 import org.eclipse.swt.SWT;\r
15 import org.eclipse.swt.custom.ScrolledComposite;\r
16 import org.eclipse.swt.layout.GridData;\r
17 import org.eclipse.swt.layout.GridLayout;\r
18 import org.eclipse.swt.widgets.Combo;\r
19 import org.eclipse.swt.widgets.Composite;\r
20 import org.eclipse.swt.widgets.Control;\r
21 import org.eclipse.swt.widgets.Event;\r
22 import org.eclipse.swt.widgets.Listener;\r
23 import org.osgi.service.prefs.BackingStoreException;\r
24 import org.osgi.service.prefs.Preferences;\r
25 import org.simantics.databoard.Accessors;\r
26 import org.simantics.databoard.Bindings;\r
27 import org.simantics.databoard.Datatypes;\r
28 import org.simantics.databoard.accessor.RecordAccessor;\r
29 import org.simantics.databoard.accessor.error.AccessorConstructionException;\r
30 import org.simantics.databoard.accessor.error.AccessorException;\r
31 import org.simantics.databoard.accessor.reference.ChildReference;\r
32 import org.simantics.databoard.accessor.reference.LabelReference;\r
33 import org.simantics.databoard.binding.RecordBinding;\r
34 import org.simantics.databoard.binding.error.BindingException;\r
35 import org.simantics.databoard.binding.error.DatatypeConstructionException;\r
36 import org.simantics.databoard.binding.error.RuntimeBindingException;\r
37 import org.simantics.databoard.binding.mutable.Variant;\r
38 import org.simantics.databoard.forms.DataboardForm;\r
39 import org.simantics.databoard.forms.DataboardForm.Problem;\r
40 import org.simantics.databoard.type.RecordType;\r
41 import org.simantics.databoard.type.UnionType;\r
42 import org.simantics.export.core.ExportContext;\r
43 import org.simantics.export.core.error.ExportException;\r
44 import org.simantics.export.core.intf.ContentType;\r
45 import org.simantics.export.core.intf.Exporter;\r
46 import org.simantics.export.core.intf.Format;\r
47 import org.simantics.export.core.intf.Publisher;\r
48 import org.simantics.export.core.manager.Content;\r
49 import org.simantics.export.core.manager.ExportAction;\r
50 import org.simantics.export.core.manager.ExportManager;\r
51 import org.simantics.export.core.manager.ExportPlan;\r
52 import org.simantics.export.core.manager.ExportWizardResult;\r
53 import org.simantics.export.core.util.ExporterUtils;\r
54 import org.simantics.utils.datastructures.Arrays;\r
55 import org.simantics.utils.datastructures.MapList;\r
56 import org.simantics.utils.datastructures.ToStringComparator;\r
57 import org.simantics.utils.datastructures.collections.CollectionUtils;\r
58 import org.simantics.utils.ui.ExceptionUtils;\r
59 import org.simantics.utils.ui.dialogs.ShowMessage;\r
60 \r
61 /**\r
62  * Dynamic Options page. Exporter, Importer and Format contributes options to this page. \r
63  *  \r
64  * @author toni.kalajainen@semantum.fi\r
65  */\r
66 public class OptionsPage extends WizardPage {\r
67 \r
68         public static String S_OUTPUT_OPTIONS = "Output Options";\r
69         public static LabelReference P_OUTPUT_OPTIONS = new LabelReference( S_OUTPUT_OPTIONS );\r
70         \r
71         /** A reference to combo box selection */\r
72         public static String S_PUBLISH = "Publish to";\r
73         public static ChildReference P_PUBLISH = ChildReference.compile(P_OUTPUT_OPTIONS, new LabelReference(S_PUBLISH));\r
74         \r
75         ExportContext ctx; \r
76         \r
77         ScrolledComposite scroll;\r
78         Composite composite;\r
79         DataboardForm form;\r
80 \r
81         List<Content> selection;\r
82         int selectionHash;\r
83         String selectedPublisherId;\r
84         \r
85         public OptionsPage(ExportContext ctx) throws ExportException {\r
86                 super("Options page", "Select export options", null);\r
87                 \r
88                 this.ctx = ctx;\r
89         }\r
90 \r
91         Listener modificationListener = new Listener() {                \r
92                 public void handleEvent(Event event) {\r
93                         if ( updatingForm ) return;\r
94                         validate();\r
95                 }\r
96         };\r
97         \r
98         boolean updatingForm;\r
99         Listener outputSettingsModifiedListener = new Listener() {              \r
100                 public void handleEvent(Event event) {\r
101                         updatingForm = true;\r
102                         try {\r
103                                 Preferences contentScopePrefs = ctx.store.node( "Selection-"+selectionHash );\r
104                                 Preferences workspaceScopePrefs = ctx.store;\r
105                                 \r
106                                 Composite outputOptions = (Composite) form.getControl(composite, P_OUTPUT_OPTIONS);\r
107                                 Combo publishTo = (Combo) form.getControl(composite, P_PUBLISH);                        \r
108                                 String newPublisherLabel = publishTo.getText();\r
109                                 Publisher newPublisher = ctx.eep.getPublisherByLabel(newPublisherLabel);\r
110                                 String newPublisherId = newPublisher==null?null:newPublisher.id();\r
111                                 //if ( newPublisherId.equals(selectedPublisherId) ) return;\r
112                                 \r
113                                 // Save Preferences\r
114                                 RecordBinding binding = ctx.databoard.getMutableBinding( form.type() );\r
115                                 Object obj = binding.createDefault();\r
116                                 form.readFields(composite, binding, obj);\r
117                                 Variant options = new Variant(binding, obj);\r
118                                 \r
119                                 Publisher oldPublisher = ctx.eep.getPublisher( selectedPublisherId );\r
120                                 if ( oldPublisher!=null ) {\r
121                                         ChildReference oldOptionsRef = new LabelReference( oldPublisher.label() );\r
122                                         try {\r
123                                                 Variant locationOptions = options.getComponent( oldOptionsRef );\r
124                                                 oldPublisher.publisherClass().savePref(locationOptions, contentScopePrefs, workspaceScopePrefs);\r
125                                         } catch ( AccessorConstructionException ee ) {}\r
126                                 }\r
127 \r
128                                 List<Content> manifest = getManifestFor(selection, options);\r
129                                 cleanPublisherFromGroup(selectedPublisherId);\r
130                                 addPublisherToGroup(newPublisherId, manifest);\r
131                                 \r
132                                 outputOptions.pack(true);\r
133                                 outputOptions.layout(true);\r
134                                 composite.pack(true);\r
135                                 composite.layout(true);\r
136                                 \r
137                                 RecordType dummy = new RecordType();\r
138                                 RecordType newPublisherOptions = newPublisher.publisherClass().locationOptions(ctx, manifest);\r
139                                 dummy.addComponent( newPublisherLabel, newPublisherOptions );\r
140                                 binding = ctx.databoard.getMutableBinding( dummy );\r
141                                 obj = binding.createDefault();\r
142                                 options = new Variant(binding, obj);\r
143                                 ChildReference locationOptionsRef = new LabelReference( newPublisherLabel );\r
144                                 Variant locationOptions = options.getComponent( locationOptionsRef );\r
145                                 newPublisher.publisherClass().fillDefaultPrefs(ctx, selection, options, locationOptions);\r
146                                 newPublisher.publisherClass().loadPref(locationOptions, contentScopePrefs, workspaceScopePrefs);        \r
147                                 //loadPublisherPref(newPublisherId, options, contentScopePrefs, workspaceScopePrefs);\r
148                                 form.writeFields(outputOptions, (RecordBinding) options.getBinding(), options.getValue());\r
149                                 \r
150                                 selectedPublisherId = newPublisherId;\r
151 \r
152                                 updatingForm = false;\r
153                                 validate();\r
154                         } catch ( BindingException e ) {\r
155                                 setErrorMessage( e.getClass().getName()+": "+ e.getMessage() );\r
156                     ExceptionUtils.logError(e);                 \r
157                         } catch (AccessorConstructionException e) {\r
158                                 setErrorMessage( e.getClass().getName()+": "+ e.getMessage() );\r
159                     ExceptionUtils.logError(e);                 \r
160                         } catch (AccessorException e) {\r
161                                 setErrorMessage( e.getClass().getName()+": "+ e.getMessage() );\r
162                     ExceptionUtils.logError(e);                 \r
163                         } catch (ExportException e) {\r
164                                 setErrorMessage( e.getClass().getName()+": "+ e.getMessage() );\r
165                     ExceptionUtils.logError(e);                 \r
166                         } finally {\r
167                                 updatingForm = false;\r
168                         }\r
169                 }\r
170         };\r
171         \r
172         @Override\r
173         public void createControl(Composite parent) {\r
174                 \r
175             scroll = new ScrolledComposite(parent, SWT.V_SCROLL);\r
176             composite = new Composite(scroll, 0);\r
177                 composite.setLayout( new GridLayout(3, false) );                        \r
178                 composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 3, 1));                   \r
179         scroll.setContent(composite);\r
180         scroll.setExpandHorizontal(true);\r
181         scroll.setExpandVertical(false);\r
182         scroll.getVerticalBar().setIncrement(scroll.getVerticalBar().getIncrement()*8);\r
183 \r
184             form = new DataboardForm();\r
185             form.setFirstColumnWidth(200);\r
186 \r
187                 composite.pack();\r
188                 setControl(scroll);\r
189         setPageComplete(true);\r
190         \r
191         }\r
192         \r
193         public void update(List<Content> contents) \r
194         {\r
195                 try {\r
196                         // 0. Initialization\r
197                         Set<String> contentUris = new TreeSet<String>();\r
198                         MapList<String, Content> uriToContentMap = new MapList<String, Content>();\r
199                         MapList<ContentType, String> contentByContentType = new MapList<ContentType, String>();\r
200                         MapList<Format, String> contentByFormat = new MapList<Format, String>();\r
201                         List<Format> formats = new ArrayList<Format>();\r
202                         Map<String, Format> contentFormatMap = new TreeMap<String, Format>( String.CASE_INSENSITIVE_ORDER );\r
203                         for (Content content : contents) {\r
204                                 contentUris.add(content.url);\r
205                                 ContentType ct = ctx.eep.getContentType( content.contentTypeId );\r
206                                 contentByContentType.add(ct, content.url);\r
207                                 Format format = ctx.eep.getFormat( content.formatId );\r
208                                 contentByFormat.add(format, content.url);\r
209                                 uriToContentMap.add(content.url, content);\r
210                         }\r
211                         formats.addAll( contentByFormat.getKeys() );\r
212                         \r
213                         Collections.sort(formats, new ToStringComparator());\r
214                                                 \r
215                         for (Content content : contents) {\r
216                                 String id = content.formatId;\r
217                                 Format format = contentFormatMap.get( id );\r
218                                 if ( format != null ) continue;\r
219                                 format = ctx.eep.getFormat(id);\r
220                                 contentFormatMap.put(id, format);\r
221                         }\r
222 \r
223                         MapList<Exporter, String> exporterContentMap = new MapList<Exporter, String>();\r
224                         TreeMap<String, Exporter> orderedExporters = new TreeMap<String, Exporter>( String.CASE_INSENSITIVE_ORDER );\r
225                         for (Content content : contents) {\r
226                                 for (Exporter exporter : ctx.eep.getExporters(content.formatId, content.contentTypeId) ) {\r
227                                         exporterContentMap.add(exporter, content.url);\r
228                                         orderedExporters.put(exporter.formatId()+exporter.contentTypeId()+exporter.exportAction().getClass(), exporter);\r
229                                 }\r
230                         }\r
231                         \r
232                         // 1. Save selections from previous form\r
233                         savePrefs();\r
234                         \r
235                         // 2. Clear previous form\r
236                         form.clear(composite);\r
237 \r
238                         // 3. Create options record\r
239                         RecordType optionsRecord = new RecordType();\r
240 \r
241                         // Add Output options box\r
242                     RecordType outputOptions = new RecordType();\r
243                         \r
244                         for ( Format format : formats ) {\r
245                                 if ( format.isGroupFormat() && contentByFormat.getValues(format).size()>1 ) {\r
246                                         outputOptions.addComponent("Merge "+format.fileext()+" content into one file", Datatypes.BOOLEAN);\r
247                                 }\r
248                                 \r
249                                 if ( format.isContainerFormat() ) {\r
250                                         List<String> formatsContentUris = contentByFormat.getValues(format);\r
251                                         int attachmentCount = 0;\r
252                                         for ( String contentUri : formatsContentUris ) {\r
253                                                 for ( Content content : uriToContentMap.getValues(contentUri) ) {\r
254                                                         if ( !content.formatId.equals(format.id()) ) attachmentCount++;\r
255                                                 }\r
256                                         }\r
257                                         // Add as possible attachment, all contents that don't have this format\r
258                                         // their their content type.\r
259                                         for ( Content content : contents ) {\r
260                                                 if ( ctx.eep.getExporters(format.id(), content.contentTypeId).length == 0) attachmentCount++;\r
261                                         }\r
262                                         \r
263                                         if ( attachmentCount > 0 ) { \r
264                                                 outputOptions.addComponent("Include attachments to "+format.fileext(), Datatypes.BOOLEAN);\r
265                                                 outputOptions.addComponent("Export attachments of "+format.fileext()+" to separate files", Datatypes.BOOLEAN);\r
266                                         }\r
267                                 }\r
268                         }\r
269                         \r
270                         UnionType publisherType = new UnionType();\r
271                         for (Publisher publisher : ctx.eep.publishers()) publisherType.addComponent(publisher.label(), Datatypes.VOID);\r
272                         outputOptions.addComponent(S_PUBLISH, publisherType);\r
273                         \r
274                     optionsRecord.addComponent(S_OUTPUT_OPTIONS, outputOptions);                    \r
275                     \r
276                         // Add Format specific boxes\r
277                         for (Format format : contentFormatMap.values()) {\r
278                                 RecordType formatOptions = format.formatActions().options(ctx);\r
279                                 if ( formatOptions==null ) continue;\r
280                                 optionsRecord.mergeRecord( formatOptions );\r
281                         }\r
282         \r
283                         // Add Exporter specific boxes\r
284                         for (Exporter exporter : orderedExporters.values()) {                           \r
285                                 List<String> exportSpecificContents = exporterContentMap.getValues(exporter);\r
286                                 if ( exportSpecificContents==null || exportSpecificContents.isEmpty() ) continue;\r
287                                 RecordType exporterOptions = exporter.exportAction().options(ctx, exportSpecificContents);\r
288                                 if ( exporterOptions == null ) continue;\r
289                                 optionsRecord.mergeRecord( exporterOptions );\r
290                         }\r
291 \r
292                         // 4. Load default and previous selections of the options ( All but publisher )\r
293                         ctx.databoard.clear();\r
294                         RecordBinding optionsBinding = ctx.databoard.getMutableBinding( optionsRecord );\r
295                         Object optionsObj = optionsBinding.createDefaultUnchecked();\r
296                         Variant options = new Variant(optionsBinding, optionsObj);\r
297                         {\r
298                                 Preferences workspaceScopePrefs = ctx.store;\r
299                                 Preferences contentScopePrefs = ctx.store( contents );\r
300                                 \r
301                                 for (Exporter exporter : orderedExporters.values()) {\r
302                                         exporter.exportAction().fillDefaultPrefs(ctx, options);\r
303                                         exporter.exportAction().loadPref(options, contentScopePrefs, workspaceScopePrefs);\r
304                                 }\r
305                                 \r
306                                 for (Format format : contentByFormat.getKeys()) {\r
307                                         format.formatActions().fillDefaultPrefs( ctx, options );\r
308                                         format.formatActions().loadPref(options, contentScopePrefs, workspaceScopePrefs);\r
309                                 }\r
310                                 \r
311                                 fillDefaultPrefs(options);\r
312                                 loadPref(options, contentScopePrefs, workspaceScopePrefs);\r
313                         }\r
314                         \r
315                         // 5. Create form\r
316                         form.addFields(composite, optionsRecord);\r
317                         form.addListener(composite, form.type(), modificationListener);\r
318                         Composite outputOptionsGroup = (Composite) form.getControl(composite, P_OUTPUT_OPTIONS);\r
319                         RecordType dummy = new RecordType();\r
320                         dummy.addComponent(S_OUTPUT_OPTIONS, outputOptions);\r
321                         form.addListener(outputOptionsGroup, dummy, outputSettingsModifiedListener);\r
322                         form.writeFields(composite, optionsBinding, optionsObj);\r
323                         \r
324                         // 6. Add publisher\r
325                         {\r
326                                 selection = contents;\r
327                                 Preferences workspaceScopePrefs = ctx.store;\r
328                                 Preferences contentScopePrefs = ctx.store.node( "Selection-"+selectionHash );\r
329                                 selectedPublisherId = ctx.store.get("publisherId", "");         \r
330                                 Publisher publisher = ctx.eep.getPublisher(selectedPublisherId);\r
331                                 if ( publisher != null ) {\r
332                                         \r
333                                         // 6A. Manifest\r
334                                         List<Content> manifest = getManifestFor(contents, options);\r
335                                         \r
336                                         // 6B. Default and previous settings\r
337                                         String label = publisher.label();\r
338                                         RecordType publisherOptionsType = publisher.publisherClass().locationOptions(ctx, manifest);\r
339                                         RecordType publisherOptionsRootType = new RecordType();\r
340                                         publisherOptionsRootType.addComponent(label, publisherOptionsType);\r
341                                         RecordBinding publisherOptionsRootBinding = ctx.databoard.getMutableBinding( publisherOptionsRootType );\r
342                                         Object publisherOptionsRootObj = publisherOptionsRootBinding.createDefaultUnchecked();\r
343                                         Variant publisherOptionsRoot = new Variant(publisherOptionsRootBinding, publisherOptionsRootObj);\r
344                                         try {\r
345                                                 ChildReference locationOptionsRef = new LabelReference( label );\r
346                                                 Variant locationOptions = publisherOptionsRoot.getComponent( locationOptionsRef );\r
347                                                 publisher.publisherClass().fillDefaultPrefs(ctx, selection, options, locationOptions);\r
348                                                 publisher.publisherClass().loadPref(locationOptions, contentScopePrefs, workspaceScopePrefs);   \r
349                                         } catch ( AccessorConstructionException ee ) {\r
350                                         }\r
351                                         \r
352                                         // 6C. Add Publisher form\r
353                                         addPublisherToGroup(selectedPublisherId, manifest);\r
354                                         form.writeFields(composite, publisherOptionsRootBinding, publisherOptionsRootObj);\r
355                                 }\r
356                         }\r
357 \r
358                         // 8. Validate page\r
359                         composite.pack();\r
360                         validate();\r
361                         \r
362                 } catch (BindingException e) {\r
363             ExceptionUtils.logError(e);                 \r
364                         ShowMessage.showError("Unexpected error", e.getClass().getName()+" "+e.getMessage());\r
365                         throw new RuntimeBindingException(e);\r
366                 } catch (ExportException e) {\r
367             ExceptionUtils.logError(e);                 \r
368                         ShowMessage.showError("Unexpected error", e.getClass().getName()+" "+e.getMessage());\r
369                 } catch (DatatypeConstructionException e) {\r
370             ExceptionUtils.logError(e);                 \r
371                         ShowMessage.showError("Unexpected error", e.getClass().getName()+" "+e.getMessage());\r
372                 } catch (AccessorConstructionException e) {\r
373             ExceptionUtils.logError(e);                 \r
374                         ShowMessage.showError("Unexpected error", e.getClass().getName()+" "+e.getMessage());\r
375                 } catch (AccessorException e) {\r
376             ExceptionUtils.logError(e);                 \r
377                         // TODO Auto-generated catch block\r
378                         e.printStackTrace();\r
379                 }\r
380                 \r
381         }\r
382 \r
383         /**\r
384          * Saves publisher prefs from the UI to preference nodes.\r
385          * \r
386          * @throws ExportException\r
387          */\r
388         void savePublisherPref(String publisherId, Variant options, Preferences contentScopePrefs, Preferences workspaceScopePrefs) throws ExportException {\r
389                 try {\r
390 //                      Preferences contentScopePrefs = ctx.store.node( "Selection-"+selectionHash );\r
391 //                      Preferences workspaceScopePrefs = ctx.store;\r
392 \r
393 //                      RecordBinding binding = ctx.databoard.getMutableBinding( form.type() );\r
394 //                      Object obj = binding.createDefault();\r
395 //                      form.readFields(composite, binding, obj);\r
396 //                      Variant options = new Variant(binding, obj);\r
397                         \r
398                         Publisher publisher = ctx.eep.getPublisher( publisherId );\r
399                         if ( publisher==null ) return;\r
400                         Variant locationOptions = options.getComponent( new LabelReference(publisher.label()) );\r
401                         publisher.publisherClass().savePref(locationOptions, contentScopePrefs, workspaceScopePrefs);\r
402 //              } catch (BindingException e) {\r
403 //                      throw new ExportException( e );\r
404                 } catch (AccessorConstructionException e) {\r
405             ExceptionUtils.logError(e);                 \r
406                         //throw new ExportException( e );\r
407 //              } catch (AccessorException e) {\r
408 //                      throw new ExportException( e );\r
409                 }\r
410         }\r
411         \r
412         void loadPublisherPref(String publisherId, Variant options, Preferences contentScopePrefs, Preferences workspaceScopePrefs) throws ExportException {\r
413                 try {\r
414 //                      Preferences contentScopePrefs = ctx.store.node( "Selection-"+selectionHash );\r
415 //                      Preferences workspaceScopePrefs = ctx.store;\r
416                         \r
417                         Publisher publisher = ctx.eep.getPublisher( publisherId );\r
418                         if ( publisher == null ) return;\r
419                         \r
420                         // There is a problem here if selection was built with manifest\r
421 //                      RecordType optionsType = publisher.publiserClass().locationOptions(ctx, selection);                     \r
422 //                      RecordBinding binding = ctx.databoard.getMutableBinding( optionsType );\r
423 //                      Object obj = binding.createDefault();\r
424 //                      Variant locationOptions = new Variant(binding, obj);\r
425                         Variant locationOptions = options.getComponent( new LabelReference( publisher.label() ) );\r
426                         publisher.publisherClass().fillDefaultPrefs(ctx, selection, options, locationOptions);\r
427                         publisher.publisherClass().loadPref(locationOptions, contentScopePrefs, workspaceScopePrefs);   \r
428 //              } catch (BindingException e) {\r
429 //                      throw new ExportException( e );\r
430                 } catch (AccessorConstructionException e) {\r
431             ExceptionUtils.logError(e);                 \r
432                         //throw new ExportException( e );\r
433 //              } catch (AccessorException e) {\r
434 //                      throw new ExportException( e );\r
435                 }\r
436         }\r
437 \r
438         /**\r
439          * Remove any publisher specific controls from output options.\r
440          */\r
441         void cleanPublisherFromGroup(String oldPublisherId) {\r
442                 Publisher publisher = ctx.eep.getPublisher(oldPublisherId);\r
443                 if ( publisher != null ) {\r
444                         String fieldName = publisher.label();\r
445                         if ( form.type().hasComponent(fieldName)) {\r
446                                 form.type().removeComponent(fieldName);\r
447                                 ctx.databoard.clear();\r
448                         }\r
449                 }\r
450                 Combo publishTo = (Combo) form.getControl(composite, P_PUBLISH);\r
451                 Composite group = (Composite) publishTo.getParent();\r
452                 Control children[] = group.getChildren();\r
453                 int index = Arrays.indexOf( children, publishTo );\r
454                 for (int i=children.length-1; i>index; i--) {\r
455                         children[i].dispose();\r
456                 }\r
457         }\r
458         \r
459         /**\r
460          * Add controls of a publisher id \r
461          * \r
462          * @param publisherId\r
463          * @throws ExportException \r
464          */\r
465         void addPublisherToGroup( String publisherId, List<Content> contents ) throws ExportException {\r
466                 try {\r
467                         Composite group = (Composite) form.getControl(composite, P_OUTPUT_OPTIONS);\r
468                         if ( group == null ) return;\r
469                         Publisher publisher = ctx.eep.getPublisher( publisherId );\r
470                         if ( publisher == null ) return;\r
471                         RecordType publisherOptions = publisher.publisherClass().locationOptions(ctx, contents);                \r
472                         //form.type().addComponent(publisher.label(), publisherOptions);\r
473                         RecordType options = new RecordType();\r
474                         options.addComponent(publisher.label(), publisherOptions);\r
475                         form.addFields(group, publisherOptions, publisher.label());\r
476                         form.addListener(group, options, modificationListener);\r
477                         ctx.databoard.clear();\r
478                 } catch (BindingException e) {\r
479                         throw new ExportException(e);\r
480                 } catch (AccessorConstructionException e) {\r
481                         throw new ExportException(e);\r
482                 } catch (AccessorException e) {\r
483                         throw new ExportException(e);\r
484                 }\r
485         }\r
486         \r
487         List<Content> getManifestFor(List<Content> selection, Variant options) {                \r
488                 try {\r
489                         ExportWizardResult result = new ExportWizardResult();\r
490                         result.options = options;\r
491                         result.accessor = Accessors.getAccessor(result.options);\r
492                         result.contents = selection;\r
493                         result.type = (RecordType) options.type();\r
494                         result.publisherId = "file";\r
495                         \r
496                         List<ExportAction> actions = new ArrayList<ExportAction>();\r
497                         List<Content> manifest = new ArrayList<Content>(); \r
498                         result.createExportActions(ctx, actions, manifest);\r
499                         return manifest;\r
500                 } catch (AccessorConstructionException e) {\r
501                         return selection;\r
502                 } catch (ExportException e) {\r
503                         e.printStackTrace();\r
504                         return selection;\r
505                 }\r
506         }       \r
507         \r
508         public ExportWizardResult getOutput()\r
509         throws ExportException\r
510         {\r
511                 ExportWizardResult result = new ExportWizardResult();\r
512                 try {\r
513                         ctx.databoard.clear();\r
514                         result.type = form.type();\r
515                     RecordBinding binding = (RecordBinding) ctx.databoard.getMutableBinding( result.type );\r
516                     Object optionsObj = binding.createDefault();\r
517                     result.options = new Variant(binding, optionsObj);\r
518                         form.readFields(composite, binding, optionsObj);\r
519                         result.accessor = Accessors.getAccessor(result.options);\r
520                         result.contents = selection;\r
521                         \r
522                         \r
523                         String publisherLabel = ExporterUtils.getUnionValue(result.accessor, P_PUBLISH);\r
524                         Publisher publisher = ctx.eep.getPublisherByLabel(publisherLabel);\r
525                         result.publisherId = publisher==null?"":publisher.id();                 \r
526                         \r
527                 } catch (BindingException e) {\r
528                         throw new ExportException(e);                   \r
529                 } catch (AccessorException e) {\r
530                         throw new ExportException(e);\r
531                 } catch (AccessorConstructionException e) {\r
532                         throw new ExportException(e);\r
533                 }\r
534                 \r
535                 return result;\r
536         }\r
537                 \r
538         void validate() {               \r
539                 List<Problem> problems = form.validate(composite);\r
540                 List<String> errs = DataboardForm.toStrings(problems);\r
541                 \r
542                 if ( errs.isEmpty() ) {\r
543                         try {\r
544                                 ExportWizardResult result = getOutput();\r
545                                 ExportPlan plan = new ExportPlan();\r
546                                 result.createPlan(ctx, plan);\r
547                                 ExportManager mgr = new ExportManager(result.options, ctx);\r
548                                 errs.addAll( mgr.validate(ctx, plan) ) ;\r
549                         } catch (ExportException e) {\r
550                                 errs.add(e.getMessage());\r
551                         }\r
552                 } else {\r
553                         CollectionUtils.unique( errs );                 \r
554                 }\r
555                 \r
556 \r
557                 setErrorMessage( errs.isEmpty() ? null : CollectionUtils.toString(errs, ", ") );\r
558                 setPageComplete( errs.isEmpty() );\r
559         }\r
560                 \r
561         /**\r
562          * Save wizard preferences\r
563          * \r
564          * @param options\r
565          * @param contentScopePrefs\r
566          * @param workspaceScopePrefs\r
567          * @throws ExportException\r
568          */\r
569         void savePref(Variant options, Preferences contentScopePrefs, Preferences workspaceScopePrefs) throws ExportException\r
570         {\r
571         try {\r
572                         RecordAccessor ra = Accessors.getAccessor(options);\r
573                         String publisherId = ExporterUtils.getUnionValue(ra, P_PUBLISH); \r
574                         Publisher publisher = ctx.eep.getPublisherByLabel(publisherId);\r
575                         if ( publisher!=null ) workspaceScopePrefs.put("publisherId", publisher.id());\r
576                         \r
577                         if ( ra.type().hasComponent(P_OUTPUT_OPTIONS.label) ) {\r
578                                 RecordAccessor rao = ra.getComponent( P_OUTPUT_OPTIONS );\r
579                                                                 \r
580                                 Pattern merge_pattern = Pattern.compile("Merge ([^\\s]*) content into one file");\r
581                                 Pattern include_pattern = Pattern.compile("Include attachments to ([^\\s]*)");\r
582                                 Pattern export_pattern = Pattern.compile("Export attachments of ([^\\s]*) to separate files");\r
583                                 \r
584                                 for (int i=0; i<rao.count(); i++) {\r
585                                         String name = rao.type().getComponent(i).name;\r
586                                         Matcher m;\r
587                                         \r
588                                         m = merge_pattern.matcher(name);\r
589                                         if ( m.matches() ) {\r
590                                                 String fileExt = m.group(1);\r
591                                                 Format format = ctx.eep.getFormatByExt(fileExt);\r
592                                                 Boolean value = (Boolean) rao.getFieldValue(i, Bindings.BOOLEAN);\r
593                                                 String key = format.id()+"_merge";\r
594                                                 contentScopePrefs.putBoolean(key, value);\r
595                                                 workspaceScopePrefs.putBoolean(key, value);\r
596                                         }\r
597                                         \r
598                                         m = include_pattern.matcher(name);\r
599                                         if ( m.matches() ) {\r
600                                                 String fileExt = m.group(1);\r
601                                                 Format format = ctx.eep.getFormatByExt(fileExt);\r
602                                                 Boolean value = (Boolean) rao.getFieldValue(i, Bindings.BOOLEAN);\r
603                                                 String key = format.id()+"_include_attachments";\r
604                                                 contentScopePrefs.putBoolean(key, value);\r
605                                                 workspaceScopePrefs.putBoolean(key, value);\r
606                                         }\r
607                                         \r
608                                         m = export_pattern.matcher(name);\r
609                                         if ( m.matches() ) {\r
610                                                 String fileExt = m.group(1);\r
611                                                 Format format = ctx.eep.getFormatByExt(fileExt);\r
612                                                 Boolean value = (Boolean) rao.getFieldValue(i, Bindings.BOOLEAN);\r
613                                                 String key = format.id()+"_export_attachments";\r
614                                                 contentScopePrefs.putBoolean(key, value);\r
615                                                 workspaceScopePrefs.putBoolean(key, value);\r
616                                         }\r
617                                 }\r
618                         }\r
619                         \r
620                 } catch (AccessorConstructionException e) {\r
621                         throw new ExportException(e);\r
622                 } catch (AccessorException e) {\r
623                         throw new ExportException(e);\r
624                 }\r
625                 \r
626         }\r
627 \r
628         /**\r
629          * Load wizard preferences\r
630          * \r
631          * @param binding\r
632          * @param options\r
633          * @param contentScopePrefs\r
634          * @param workspaceScopePrefs\r
635          * @throws ExportException\r
636          */\r
637         void loadPref(Variant options, Preferences contentScopePrefs, Preferences workspaceScopePrefs) throws ExportException\r
638         {\r
639                 //Preferences workspaceScopePrefs = ctx.store;\r
640         try {\r
641                         RecordAccessor ra = Accessors.getAccessor(options);             \r
642                         String publisherId = workspaceScopePrefs.get("publisherId", "");\r
643                         Publisher publisher = ctx.eep.getPublisher(publisherId);\r
644                         if ( publisher != null ) ExporterUtils.setUnionValue(ra, P_PUBLISH, publisher.label());\r
645                         \r
646                         if ( ra.type().hasComponent(P_OUTPUT_OPTIONS.label) ) {\r
647                                 RecordAccessor rao = ra.getComponent( P_OUTPUT_OPTIONS );\r
648                                                                 \r
649                                 for (Format format : ctx.eep.formats()) {\r
650                                         if ( format.isGroupFormat() ) {\r
651                                                 String key = format.id()+"_merge";\r
652                                                 Boolean value = null;\r
653                                                 if ( containsKey(contentScopePrefs, key) ) {\r
654                                                         value = contentScopePrefs.getBoolean(key, false); \r
655                                                 } else if ( containsKey(workspaceScopePrefs, key) ) {\r
656                                                         value = workspaceScopePrefs.getBoolean(key, false);\r
657                                                 }\r
658                                                                                         \r
659                                                 if ( value != null ) {\r
660                                                         String key2 = "Merge "+format.fileext()+" content into one file";\r
661                                                         int index = rao.type().getComponentIndex2(key2);\r
662                                                         if ( index>=0 ) {\r
663                                                                 rao.setFieldValue(index, Bindings.BOOLEAN, value);\r
664                                                         }\r
665                                                 }                                       \r
666                                         }\r
667                                         \r
668                                         if ( format.isContainerFormat() ) {\r
669                                                 String key = format.id()+"_include_attachments";\r
670                                                 Boolean value = null;\r
671                                                 if ( containsKey(contentScopePrefs, key) ) {\r
672                                                         value = contentScopePrefs.getBoolean(key, false); \r
673                                                 } else if ( containsKey(workspaceScopePrefs, key) ) {\r
674                                                         value = workspaceScopePrefs.getBoolean(key, false);\r
675                                                 }\r
676                                                                                         \r
677                                                 if ( value != null ) {\r
678                                                         String key2 = "Include attachments to "+format.fileext();\r
679                                                         int index = rao.type().getComponentIndex2(key2);\r
680                                                         if ( index>=0 ) {\r
681                                                                 rao.setFieldValue(index, Bindings.BOOLEAN, value);\r
682                                                         }\r
683                                                 }                                       \r
684                                         }\r
685                                         \r
686                                         if ( format.isContainerFormat() ) {\r
687                                                 String key = format.id()+"_export_attachments";\r
688                                                 Boolean value = null;\r
689                                                 if ( containsKey(contentScopePrefs, key) ) {\r
690                                                         value = contentScopePrefs.getBoolean(key, false); \r
691                                                 } else if ( containsKey(workspaceScopePrefs, key) ) {\r
692                                                         value = workspaceScopePrefs.getBoolean(key, false);\r
693                                                 }\r
694                                                                                         \r
695                                                 if ( value != null ) {\r
696                                                         String key2 = "Export attachments of "+format.fileext()+" to separate files";\r
697                                                         int index = rao.type().getComponentIndex2(key2);\r
698                                                         if ( index>=0 ) {\r
699                                                                 rao.setFieldValue(index, Bindings.BOOLEAN, value);\r
700                                                         }\r
701                                                 }                                       \r
702                                         }\r
703                                         \r
704                                 }\r
705                         }\r
706                                         \r
707                 } catch (AccessorConstructionException e) {\r
708                         throw new ExportException(e);\r
709                 } catch (AccessorException e) {\r
710                         throw new ExportException(e);\r
711                 }               \r
712         }\r
713         \r
714         /**\r
715          * Save selections from previous form\r
716          */\r
717         public void savePrefs() throws ExportException {\r
718                 try {\r
719                         int oldSelectionHash = selectionHash;                   \r
720                         Preferences contentScopePrefs = ctx.store.node( "Selection-"+oldSelectionHash );\r
721                         Preferences workspaceScopePrefs = ctx.store;\r
722                                         \r
723                         RecordBinding binding = ctx.databoard.getMutableBinding( form.type() );\r
724                         Object obj = binding.createDefault();\r
725                         Variant options = new Variant(binding, obj);\r
726                         form.readFields(composite, binding, obj);\r
727                                                 \r
728                         Combo publishTo = (Combo) form.getControl(composite, P_PUBLISH);                \r
729                         String publisherLabel = publishTo==null?null:publishTo.getText();\r
730                         if ( publisherLabel != null ) {\r
731                                 Publisher publisher = ctx.eep.getPublisherByLabel( publisherLabel );\r
732                                 if ( publisher!=null ) {\r
733                                         try {\r
734                                                 ChildReference locationOptionsRef = new LabelReference(publisher.label());\r
735                                                 Variant locationOptions = options.getComponent( locationOptionsRef );\r
736                                                 publisher.publisherClass().savePref(locationOptions, contentScopePrefs, workspaceScopePrefs);\r
737                                         } catch ( AccessorConstructionException e ) {} \r
738                                 }\r
739                         }\r
740                         \r
741                         for (Exporter exporter : ctx.eep.exporters()) {\r
742                                 exporter.exportAction().savePref(options, contentScopePrefs, workspaceScopePrefs);\r
743                         }\r
744                                         \r
745                         for (Format format : ctx.eep.formats()) {\r
746                                 format.formatActions().savePref(options, contentScopePrefs, workspaceScopePrefs);\r
747                         }                               \r
748                                         \r
749                         savePref(options, contentScopePrefs, workspaceScopePrefs);\r
750                 } catch (BindingException e) {\r
751                         throw new ExportException( e ); \r
752                 } catch (AccessorConstructionException e) {\r
753                         throw new ExportException( e ); \r
754                 } catch (AccessorException e) {\r
755                         throw new ExportException( e ); \r
756                 } catch (ExportException e) {\r
757                         throw new ExportException( e ); \r
758                 }\r
759         }\r
760 \r
761         public void fillDefaultPrefs(Variant options) throws ExportException {\r
762         try {\r
763                         RecordAccessor ra = Accessors.getAccessor(options);\r
764 \r
765                         if ( ra.type().hasComponent(P_OUTPUT_OPTIONS.label) ) {\r
766                                 RecordAccessor rao = ra.getComponent( P_OUTPUT_OPTIONS );\r
767                                 \r
768                                 for (Format format : ctx.eep.formats()) {\r
769                                         if ( format.isContainerFormat() ) {\r
770                                                 String key = "Include attachments to "+format.fileext();\r
771                                                 int index = rao.type().getComponentIndex2(key);\r
772                                                 if ( index>=0 ) rao.setFieldValue(index, Bindings.BOOLEAN, true);\r
773                                                 \r
774                                                 key = "Export attachments of "+format.fileext()+" to separate files";;\r
775                                                 index = rao.type().getComponentIndex2(key);\r
776                                                 if ( index>=0 ) rao.setFieldValue(index, Bindings.BOOLEAN, true);\r
777                                         }                       \r
778                                 }\r
779                                 \r
780                         }\r
781                 \r
782                 } catch (AccessorConstructionException e) {\r
783                         throw new ExportException(e);\r
784                 } catch (AccessorException e) {\r
785                         throw new ExportException(e);\r
786                 }\r
787         }       \r
788         \r
789         static boolean containsKey(Preferences pref, String key) {\r
790                 try {\r
791                         for (String x : pref.keys()) if ( x.equals(key) ) return true;\r
792                 } catch (BackingStoreException e) {\r
793                         e.printStackTrace();\r
794                 } \r
795                 return false;           \r
796         }\r
797                 \r
798 }\r