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