+package org.simantics.export.ui;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collections;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.Set;\r
+import java.util.TreeMap;\r
+import java.util.TreeSet;\r
+import java.util.regex.Matcher;\r
+import java.util.regex.Pattern;\r
+\r
+import org.eclipse.jface.wizard.WizardPage;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.custom.ScrolledComposite;\r
+import org.eclipse.swt.layout.GridData;\r
+import org.eclipse.swt.layout.GridLayout;\r
+import org.eclipse.swt.widgets.Combo;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Control;\r
+import org.eclipse.swt.widgets.Event;\r
+import org.eclipse.swt.widgets.Listener;\r
+import org.osgi.service.prefs.BackingStoreException;\r
+import org.osgi.service.prefs.Preferences;\r
+import org.simantics.databoard.Accessors;\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.databoard.Datatypes;\r
+import org.simantics.databoard.accessor.RecordAccessor;\r
+import org.simantics.databoard.accessor.error.AccessorConstructionException;\r
+import org.simantics.databoard.accessor.error.AccessorException;\r
+import org.simantics.databoard.accessor.reference.ChildReference;\r
+import org.simantics.databoard.accessor.reference.LabelReference;\r
+import org.simantics.databoard.binding.RecordBinding;\r
+import org.simantics.databoard.binding.error.BindingException;\r
+import org.simantics.databoard.binding.error.DatatypeConstructionException;\r
+import org.simantics.databoard.binding.error.RuntimeBindingException;\r
+import org.simantics.databoard.binding.mutable.Variant;\r
+import org.simantics.databoard.forms.DataboardForm;\r
+import org.simantics.databoard.forms.DataboardForm.Problem;\r
+import org.simantics.databoard.type.RecordType;\r
+import org.simantics.databoard.type.UnionType;\r
+import org.simantics.export.core.ExportContext;\r
+import org.simantics.export.core.error.ExportException;\r
+import org.simantics.export.core.intf.ContentType;\r
+import org.simantics.export.core.intf.Exporter;\r
+import org.simantics.export.core.intf.Format;\r
+import org.simantics.export.core.intf.Publisher;\r
+import org.simantics.export.core.manager.Content;\r
+import org.simantics.export.core.manager.ExportAction;\r
+import org.simantics.export.core.manager.ExportManager;\r
+import org.simantics.export.core.manager.ExportPlan;\r
+import org.simantics.export.core.manager.ExportWizardResult;\r
+import org.simantics.export.core.util.ExporterUtils;\r
+import org.simantics.utils.datastructures.Arrays;\r
+import org.simantics.utils.datastructures.MapList;\r
+import org.simantics.utils.datastructures.ToStringComparator;\r
+import org.simantics.utils.datastructures.collections.CollectionUtils;\r
+import org.simantics.utils.ui.ExceptionUtils;\r
+import org.simantics.utils.ui.dialogs.ShowMessage;\r
+\r
+/**\r
+ * Dynamic Options page. Exporter, Importer and Format contributes options to this page. \r
+ * \r
+ * @author toni.kalajainen@semantum.fi\r
+ */\r
+public class OptionsPage extends WizardPage {\r
+\r
+ public static String S_OUTPUT_OPTIONS = "Output Options";\r
+ public static LabelReference P_OUTPUT_OPTIONS = new LabelReference( S_OUTPUT_OPTIONS );\r
+ \r
+ /** A reference to combo box selection */\r
+ public static String S_PUBLISH = "Publish to";\r
+ public static ChildReference P_PUBLISH = ChildReference.compile(P_OUTPUT_OPTIONS, new LabelReference(S_PUBLISH));\r
+ \r
+ ExportContext ctx; \r
+ \r
+ ScrolledComposite scroll;\r
+ Composite composite;\r
+ DataboardForm form;\r
+\r
+ List<Content> selection;\r
+ int selectionHash;\r
+ String selectedPublisherId;\r
+ \r
+ public OptionsPage(ExportContext ctx) throws ExportException {\r
+ super("Options page", "Select export options", null);\r
+ \r
+ this.ctx = ctx;\r
+ }\r
+\r
+ Listener modificationListener = new Listener() { \r
+ public void handleEvent(Event event) {\r
+ if ( updatingForm ) return;\r
+ validate();\r
+ }\r
+ };\r
+ \r
+ boolean updatingForm;\r
+ Listener outputSettingsModifiedListener = new Listener() { \r
+ public void handleEvent(Event event) {\r
+ updatingForm = true;\r
+ try {\r
+ Preferences contentScopePrefs = ctx.store.node( "Selection-"+selectionHash );\r
+ Preferences workspaceScopePrefs = ctx.store;\r
+ \r
+ Composite outputOptions = (Composite) form.getControl(composite, P_OUTPUT_OPTIONS);\r
+ Combo publishTo = (Combo) form.getControl(composite, P_PUBLISH); \r
+ String newPublisherLabel = publishTo.getText();\r
+ Publisher newPublisher = ctx.eep.getPublisherByLabel(newPublisherLabel);\r
+ String newPublisherId = newPublisher==null?null:newPublisher.id();\r
+ //if ( newPublisherId.equals(selectedPublisherId) ) return;\r
+ \r
+ // Save Preferences\r
+ RecordBinding binding = ctx.databoard.getMutableBinding( form.type() );\r
+ Object obj = binding.createDefault();\r
+ form.readFields(composite, binding, obj);\r
+ Variant options = new Variant(binding, obj);\r
+ \r
+ Publisher oldPublisher = ctx.eep.getPublisher( selectedPublisherId );\r
+ if ( oldPublisher!=null ) {\r
+ ChildReference oldOptionsRef = new LabelReference( oldPublisher.label() );\r
+ try {\r
+ Variant locationOptions = options.getComponent( oldOptionsRef );\r
+ oldPublisher.publisherClass().savePref(locationOptions, contentScopePrefs, workspaceScopePrefs);\r
+ } catch ( AccessorConstructionException ee ) {}\r
+ }\r
+\r
+ List<Content> manifest = getManifestFor(selection, options);\r
+ cleanPublisherFromGroup(selectedPublisherId);\r
+ addPublisherToGroup(newPublisherId, manifest);\r
+ \r
+ outputOptions.pack(true);\r
+ outputOptions.layout(true);\r
+ composite.pack(true);\r
+ composite.layout(true);\r
+ \r
+ RecordType dummy = new RecordType();\r
+ RecordType newPublisherOptions = newPublisher.publisherClass().locationOptions(ctx, manifest);\r
+ dummy.addComponent( newPublisherLabel, newPublisherOptions );\r
+ binding = ctx.databoard.getMutableBinding( dummy );\r
+ obj = binding.createDefault();\r
+ options = new Variant(binding, obj);\r
+ ChildReference locationOptionsRef = new LabelReference( newPublisherLabel );\r
+ Variant locationOptions = options.getComponent( locationOptionsRef );\r
+ newPublisher.publisherClass().fillDefaultPrefs(ctx, selection, options, locationOptions);\r
+ newPublisher.publisherClass().loadPref(locationOptions, contentScopePrefs, workspaceScopePrefs); \r
+ //loadPublisherPref(newPublisherId, options, contentScopePrefs, workspaceScopePrefs);\r
+ form.writeFields(outputOptions, (RecordBinding) options.getBinding(), options.getValue());\r
+ \r
+ selectedPublisherId = newPublisherId;\r
+\r
+ updatingForm = false;\r
+ validate();\r
+ } catch ( BindingException e ) {\r
+ setErrorMessage( e.getClass().getName()+": "+ e.getMessage() );\r
+ ExceptionUtils.logError(e); \r
+ } catch (AccessorConstructionException e) {\r
+ setErrorMessage( e.getClass().getName()+": "+ e.getMessage() );\r
+ ExceptionUtils.logError(e); \r
+ } catch (AccessorException e) {\r
+ setErrorMessage( e.getClass().getName()+": "+ e.getMessage() );\r
+ ExceptionUtils.logError(e); \r
+ } catch (ExportException e) {\r
+ setErrorMessage( e.getClass().getName()+": "+ e.getMessage() );\r
+ ExceptionUtils.logError(e); \r
+ } finally {\r
+ updatingForm = false;\r
+ }\r
+ }\r
+ };\r
+ \r
+ @Override\r
+ public void createControl(Composite parent) {\r
+ \r
+ scroll = new ScrolledComposite(parent, SWT.V_SCROLL);\r
+ composite = new Composite(scroll, 0);\r
+ composite.setLayout( new GridLayout(3, false) ); \r
+ composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 3, 1)); \r
+ scroll.setContent(composite);\r
+ scroll.setExpandHorizontal(true);\r
+ scroll.setExpandVertical(false);\r
+ scroll.getVerticalBar().setIncrement(scroll.getVerticalBar().getIncrement()*8);\r
+\r
+ form = new DataboardForm();\r
+ form.setFirstColumnWidth(200);\r
+\r
+ composite.pack();\r
+ setControl(scroll);\r
+ setPageComplete(true);\r
+ \r
+ }\r
+ \r
+ public void update(List<Content> contents) \r
+ {\r
+ try {\r
+ // 0. Initialization\r
+ Set<String> contentUris = new TreeSet<String>();\r
+ MapList<String, Content> uriToContentMap = new MapList<String, Content>();\r
+ MapList<ContentType, String> contentByContentType = new MapList<ContentType, String>();\r
+ MapList<Format, String> contentByFormat = new MapList<Format, String>();\r
+ List<Format> formats = new ArrayList<Format>();\r
+ Map<String, Format> contentFormatMap = new TreeMap<String, Format>( String.CASE_INSENSITIVE_ORDER );\r
+ for (Content content : contents) {\r
+ contentUris.add(content.url);\r
+ ContentType ct = ctx.eep.getContentType( content.contentTypeId );\r
+ contentByContentType.add(ct, content.url);\r
+ Format format = ctx.eep.getFormat( content.formatId );\r
+ contentByFormat.add(format, content.url);\r
+ uriToContentMap.add(content.url, content);\r
+ }\r
+ formats.addAll( contentByFormat.getKeys() );\r
+ \r
+ Collections.sort(formats, new ToStringComparator());\r
+ \r
+ for (Content content : contents) {\r
+ String id = content.formatId;\r
+ Format format = contentFormatMap.get( id );\r
+ if ( format != null ) continue;\r
+ format = ctx.eep.getFormat(id);\r
+ contentFormatMap.put(id, format);\r
+ }\r
+\r
+ MapList<Exporter, String> exporterContentMap = new MapList<Exporter, String>();\r
+ TreeMap<String, Exporter> orderedExporters = new TreeMap<String, Exporter>( String.CASE_INSENSITIVE_ORDER );\r
+ for (Content content : contents) {\r
+ for (Exporter exporter : ctx.eep.getExporters(content.formatId, content.contentTypeId) ) {\r
+ exporterContentMap.add(exporter, content.url);\r
+ orderedExporters.put(exporter.formatId()+exporter.contentTypeId()+exporter.exportAction().getClass(), exporter);\r
+ }\r
+ }\r
+ \r
+ // 1. Save selections from previous form\r
+ savePrefs();\r
+ \r
+ // 2. Clear previous form\r
+ form.clear(composite);\r
+\r
+ // 3. Create options record\r
+ RecordType optionsRecord = new RecordType();\r
+\r
+ // Add Output options box\r
+ RecordType outputOptions = new RecordType();\r
+ \r
+ for ( Format format : formats ) {\r
+ if ( format.isGroupFormat() && contentByFormat.getValues(format).size()>1 ) {\r
+ outputOptions.addComponent("Merge "+format.fileext()+" content into one file", Datatypes.BOOLEAN);\r
+ }\r
+ \r
+ if ( format.isContainerFormat() ) {\r
+ List<String> formatsContentUris = contentByFormat.getValues(format);\r
+ int attachmentCount = 0;\r
+ for ( String contentUri : formatsContentUris ) {\r
+ for ( Content content : uriToContentMap.getValues(contentUri) ) {\r
+ if ( !content.formatId.equals(format.id()) ) attachmentCount++;\r
+ }\r
+ }\r
+ // Add as possible attachment, all contents that don't have this format\r
+ // their their content type.\r
+ for ( Content content : contents ) {\r
+ if ( ctx.eep.getExporters(format.id(), content.contentTypeId).length == 0) attachmentCount++;\r
+ }\r
+ \r
+ if ( attachmentCount > 0 ) { \r
+ outputOptions.addComponent("Include attachments to "+format.fileext(), Datatypes.BOOLEAN);\r
+ outputOptions.addComponent("Export attachments of "+format.fileext()+" to separate files", Datatypes.BOOLEAN);\r
+ }\r
+ }\r
+ }\r
+ \r
+ UnionType publisherType = new UnionType();\r
+ for (Publisher publisher : ctx.eep.publishers()) publisherType.addComponent(publisher.label(), Datatypes.VOID);\r
+ outputOptions.addComponent(S_PUBLISH, publisherType);\r
+ \r
+ optionsRecord.addComponent(S_OUTPUT_OPTIONS, outputOptions); \r
+ \r
+ // Add Format specific boxes\r
+ for (Format format : contentFormatMap.values()) {\r
+ RecordType formatOptions = format.formatActions().options(ctx);\r
+ if ( formatOptions==null ) continue;\r
+ optionsRecord.mergeRecord( formatOptions );\r
+ }\r
+ \r
+ // Add Exporter specific boxes\r
+ for (Exporter exporter : orderedExporters.values()) { \r
+ List<String> exportSpecificContents = exporterContentMap.getValues(exporter);\r
+ if ( exportSpecificContents==null || exportSpecificContents.isEmpty() ) continue;\r
+ RecordType exporterOptions = exporter.exportAction().options(ctx, exportSpecificContents);\r
+ if ( exporterOptions == null ) continue;\r
+ optionsRecord.mergeRecord( exporterOptions );\r
+ }\r
+\r
+ // 4. Load default and previous selections of the options ( All but publisher )\r
+ ctx.databoard.clear();\r
+ RecordBinding optionsBinding = ctx.databoard.getMutableBinding( optionsRecord );\r
+ Object optionsObj = optionsBinding.createDefaultUnchecked();\r
+ Variant options = new Variant(optionsBinding, optionsObj);\r
+ {\r
+ Preferences workspaceScopePrefs = ctx.store;\r
+ Preferences contentScopePrefs = ctx.store( contents );\r
+ \r
+ for (Exporter exporter : orderedExporters.values()) {\r
+ exporter.exportAction().fillDefaultPrefs(ctx, options);\r
+ exporter.exportAction().loadPref(options, contentScopePrefs, workspaceScopePrefs);\r
+ }\r
+ \r
+ for (Format format : contentByFormat.getKeys()) {\r
+ format.formatActions().fillDefaultPrefs( ctx, options );\r
+ format.formatActions().loadPref(options, contentScopePrefs, workspaceScopePrefs);\r
+ }\r
+ \r
+ fillDefaultPrefs(options);\r
+ loadPref(options, contentScopePrefs, workspaceScopePrefs);\r
+ }\r
+ \r
+ // 5. Create form\r
+ form.addFields(composite, optionsRecord);\r
+ form.addListener(composite, form.type(), modificationListener);\r
+ Composite outputOptionsGroup = (Composite) form.getControl(composite, P_OUTPUT_OPTIONS);\r
+ RecordType dummy = new RecordType();\r
+ dummy.addComponent(S_OUTPUT_OPTIONS, outputOptions);\r
+ form.addListener(outputOptionsGroup, dummy, outputSettingsModifiedListener);\r
+ form.writeFields(composite, optionsBinding, optionsObj);\r
+ \r
+ // 6. Add publisher\r
+ {\r
+ selection = contents;\r
+ Preferences workspaceScopePrefs = ctx.store;\r
+ Preferences contentScopePrefs = ctx.store.node( "Selection-"+selectionHash );\r
+ selectedPublisherId = ctx.store.get("publisherId", ""); \r
+ Publisher publisher = ctx.eep.getPublisher(selectedPublisherId);\r
+ if ( publisher != null ) {\r
+ \r
+ // 6A. Manifest\r
+ List<Content> manifest = getManifestFor(contents, options);\r
+ \r
+ // 6B. Default and previous settings\r
+ String label = publisher.label();\r
+ RecordType publisherOptionsType = publisher.publisherClass().locationOptions(ctx, manifest);\r
+ RecordType publisherOptionsRootType = new RecordType();\r
+ publisherOptionsRootType.addComponent(label, publisherOptionsType);\r
+ RecordBinding publisherOptionsRootBinding = ctx.databoard.getMutableBinding( publisherOptionsRootType );\r
+ Object publisherOptionsRootObj = publisherOptionsRootBinding.createDefaultUnchecked();\r
+ Variant publisherOptionsRoot = new Variant(publisherOptionsRootBinding, publisherOptionsRootObj);\r
+ try {\r
+ ChildReference locationOptionsRef = new LabelReference( label );\r
+ Variant locationOptions = publisherOptionsRoot.getComponent( locationOptionsRef );\r
+ publisher.publisherClass().fillDefaultPrefs(ctx, selection, options, locationOptions);\r
+ publisher.publisherClass().loadPref(locationOptions, contentScopePrefs, workspaceScopePrefs); \r
+ } catch ( AccessorConstructionException ee ) {\r
+ }\r
+ \r
+ // 6C. Add Publisher form\r
+ addPublisherToGroup(selectedPublisherId, manifest);\r
+ form.writeFields(composite, publisherOptionsRootBinding, publisherOptionsRootObj);\r
+ }\r
+ }\r
+\r
+ // 8. Validate page\r
+ composite.pack();\r
+ validate();\r
+ \r
+ } catch (BindingException e) {\r
+ ExceptionUtils.logError(e); \r
+ ShowMessage.showError("Unexpected error", e.getClass().getName()+" "+e.getMessage());\r
+ throw new RuntimeBindingException(e);\r
+ } catch (ExportException e) {\r
+ ExceptionUtils.logError(e); \r
+ ShowMessage.showError("Unexpected error", e.getClass().getName()+" "+e.getMessage());\r
+ } catch (DatatypeConstructionException e) {\r
+ ExceptionUtils.logError(e); \r
+ ShowMessage.showError("Unexpected error", e.getClass().getName()+" "+e.getMessage());\r
+ } catch (AccessorConstructionException e) {\r
+ ExceptionUtils.logError(e); \r
+ ShowMessage.showError("Unexpected error", e.getClass().getName()+" "+e.getMessage());\r
+ } catch (AccessorException e) {\r
+ ExceptionUtils.logError(e); \r
+ // TODO Auto-generated catch block\r
+ e.printStackTrace();\r
+ }\r
+ \r
+ }\r
+\r
+ /**\r
+ * Saves publisher prefs from the UI to preference nodes.\r
+ * \r
+ * @throws ExportException\r
+ */\r
+ void savePublisherPref(String publisherId, Variant options, Preferences contentScopePrefs, Preferences workspaceScopePrefs) throws ExportException {\r
+ try {\r
+// Preferences contentScopePrefs = ctx.store.node( "Selection-"+selectionHash );\r
+// Preferences workspaceScopePrefs = ctx.store;\r
+\r
+// RecordBinding binding = ctx.databoard.getMutableBinding( form.type() );\r
+// Object obj = binding.createDefault();\r
+// form.readFields(composite, binding, obj);\r
+// Variant options = new Variant(binding, obj);\r
+ \r
+ Publisher publisher = ctx.eep.getPublisher( publisherId );\r
+ if ( publisher==null ) return;\r
+ Variant locationOptions = options.getComponent( new LabelReference(publisher.label()) );\r
+ publisher.publisherClass().savePref(locationOptions, contentScopePrefs, workspaceScopePrefs);\r
+// } catch (BindingException e) {\r
+// throw new ExportException( e );\r
+ } catch (AccessorConstructionException e) {\r
+ ExceptionUtils.logError(e); \r
+ //throw new ExportException( e );\r
+// } catch (AccessorException e) {\r
+// throw new ExportException( e );\r
+ }\r
+ }\r
+ \r
+ void loadPublisherPref(String publisherId, Variant options, Preferences contentScopePrefs, Preferences workspaceScopePrefs) throws ExportException {\r
+ try {\r
+// Preferences contentScopePrefs = ctx.store.node( "Selection-"+selectionHash );\r
+// Preferences workspaceScopePrefs = ctx.store;\r
+ \r
+ Publisher publisher = ctx.eep.getPublisher( publisherId );\r
+ if ( publisher == null ) return;\r
+ \r
+ // There is a problem here if selection was built with manifest\r
+// RecordType optionsType = publisher.publiserClass().locationOptions(ctx, selection); \r
+// RecordBinding binding = ctx.databoard.getMutableBinding( optionsType );\r
+// Object obj = binding.createDefault();\r
+// Variant locationOptions = new Variant(binding, obj);\r
+ Variant locationOptions = options.getComponent( new LabelReference( publisher.label() ) );\r
+ publisher.publisherClass().fillDefaultPrefs(ctx, selection, options, locationOptions);\r
+ publisher.publisherClass().loadPref(locationOptions, contentScopePrefs, workspaceScopePrefs); \r
+// } catch (BindingException e) {\r
+// throw new ExportException( e );\r
+ } catch (AccessorConstructionException e) {\r
+ ExceptionUtils.logError(e); \r
+ //throw new ExportException( e );\r
+// } catch (AccessorException e) {\r
+// throw new ExportException( e );\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Remove any publisher specific controls from output options.\r
+ */\r
+ void cleanPublisherFromGroup(String oldPublisherId) {\r
+ Publisher publisher = ctx.eep.getPublisher(oldPublisherId);\r
+ if ( publisher != null ) {\r
+ String fieldName = publisher.label();\r
+ if ( form.type().hasComponent(fieldName)) {\r
+ form.type().removeComponent(fieldName);\r
+ ctx.databoard.clear();\r
+ }\r
+ }\r
+ Combo publishTo = (Combo) form.getControl(composite, P_PUBLISH);\r
+ Composite group = (Composite) publishTo.getParent();\r
+ Control children[] = group.getChildren();\r
+ int index = Arrays.indexOf( children, publishTo );\r
+ for (int i=children.length-1; i>index; i--) {\r
+ children[i].dispose();\r
+ }\r
+ }\r
+ \r
+ /**\r
+ * Add controls of a publisher id \r
+ * \r
+ * @param publisherId\r
+ * @throws ExportException \r
+ */\r
+ void addPublisherToGroup( String publisherId, List<Content> contents ) throws ExportException {\r
+ try {\r
+ Composite group = (Composite) form.getControl(composite, P_OUTPUT_OPTIONS);\r
+ if ( group == null ) return;\r
+ Publisher publisher = ctx.eep.getPublisher( publisherId );\r
+ if ( publisher == null ) return;\r
+ RecordType publisherOptions = publisher.publisherClass().locationOptions(ctx, contents); \r
+ //form.type().addComponent(publisher.label(), publisherOptions);\r
+ RecordType options = new RecordType();\r
+ options.addComponent(publisher.label(), publisherOptions);\r
+ form.addFields(group, publisherOptions, publisher.label());\r
+ form.addListener(group, options, modificationListener);\r
+ ctx.databoard.clear();\r
+ } catch (BindingException e) {\r
+ throw new ExportException(e);\r
+ } catch (AccessorConstructionException e) {\r
+ throw new ExportException(e);\r
+ } catch (AccessorException e) {\r
+ throw new ExportException(e);\r
+ }\r
+ }\r
+ \r
+ List<Content> getManifestFor(List<Content> selection, Variant options) { \r
+ try {\r
+ ExportWizardResult result = new ExportWizardResult();\r
+ result.options = options;\r
+ result.accessor = Accessors.getAccessor(result.options);\r
+ result.contents = selection;\r
+ result.type = (RecordType) options.type();\r
+ result.publisherId = "file";\r
+ \r
+ List<ExportAction> actions = new ArrayList<ExportAction>();\r
+ List<Content> manifest = new ArrayList<Content>(); \r
+ result.createExportActions(ctx, actions, manifest);\r
+ return manifest;\r
+ } catch (AccessorConstructionException e) {\r
+ return selection;\r
+ } catch (ExportException e) {\r
+ e.printStackTrace();\r
+ return selection;\r
+ }\r
+ } \r
+ \r
+ public ExportWizardResult getOutput()\r
+ throws ExportException\r
+ {\r
+ ExportWizardResult result = new ExportWizardResult();\r
+ try {\r
+ ctx.databoard.clear();\r
+ result.type = form.type();\r
+ RecordBinding binding = (RecordBinding) ctx.databoard.getMutableBinding( result.type );\r
+ Object optionsObj = binding.createDefault();\r
+ result.options = new Variant(binding, optionsObj);\r
+ form.readFields(composite, binding, optionsObj);\r
+ result.accessor = Accessors.getAccessor(result.options);\r
+ result.contents = selection;\r
+ \r
+ \r
+ String publisherLabel = ExporterUtils.getUnionValue(result.accessor, P_PUBLISH);\r
+ Publisher publisher = ctx.eep.getPublisherByLabel(publisherLabel);\r
+ result.publisherId = publisher==null?"":publisher.id(); \r
+ \r
+ } catch (BindingException e) {\r
+ throw new ExportException(e); \r
+ } catch (AccessorException e) {\r
+ throw new ExportException(e);\r
+ } catch (AccessorConstructionException e) {\r
+ throw new ExportException(e);\r
+ }\r
+ \r
+ return result;\r
+ }\r
+ \r
+ void validate() { \r
+ List<Problem> problems = form.validate(composite);\r
+ List<String> errs = DataboardForm.toStrings(problems);\r
+ \r
+ if ( errs.isEmpty() ) {\r
+ try {\r
+ ExportWizardResult result = getOutput();\r
+ ExportPlan plan = new ExportPlan();\r
+ result.createPlan(ctx, plan);\r
+ ExportManager mgr = new ExportManager(result.options, ctx);\r
+ errs.addAll( mgr.validate(ctx, plan) ) ;\r
+ } catch (ExportException e) {\r
+ errs.add(e.getMessage());\r
+ }\r
+ } else {\r
+ CollectionUtils.unique( errs ); \r
+ }\r
+ \r
+\r
+ setErrorMessage( errs.isEmpty() ? null : CollectionUtils.toString(errs, ", ") );\r
+ setPageComplete( errs.isEmpty() );\r
+ }\r
+ \r
+ /**\r
+ * Save wizard preferences\r
+ * \r
+ * @param options\r
+ * @param contentScopePrefs\r
+ * @param workspaceScopePrefs\r
+ * @throws ExportException\r
+ */\r
+ void savePref(Variant options, Preferences contentScopePrefs, Preferences workspaceScopePrefs) throws ExportException\r
+ {\r
+ try {\r
+ RecordAccessor ra = Accessors.getAccessor(options);\r
+ String publisherId = ExporterUtils.getUnionValue(ra, P_PUBLISH); \r
+ Publisher publisher = ctx.eep.getPublisherByLabel(publisherId);\r
+ if ( publisher!=null ) workspaceScopePrefs.put("publisherId", publisher.id());\r
+ \r
+ if ( ra.type().hasComponent(P_OUTPUT_OPTIONS.label) ) {\r
+ RecordAccessor rao = ra.getComponent( P_OUTPUT_OPTIONS );\r
+ \r
+ Pattern merge_pattern = Pattern.compile("Merge ([^\\s]*) content into one file");\r
+ Pattern include_pattern = Pattern.compile("Include attachments to ([^\\s]*)");\r
+ Pattern export_pattern = Pattern.compile("Export attachments of ([^\\s]*) to separate files");\r
+ \r
+ for (int i=0; i<rao.count(); i++) {\r
+ String name = rao.type().getComponent(i).name;\r
+ Matcher m;\r
+ \r
+ m = merge_pattern.matcher(name);\r
+ if ( m.matches() ) {\r
+ String fileExt = m.group(1);\r
+ Format format = ctx.eep.getFormatByExt(fileExt);\r
+ Boolean value = (Boolean) rao.getFieldValue(i, Bindings.BOOLEAN);\r
+ String key = format.id()+"_merge";\r
+ contentScopePrefs.putBoolean(key, value);\r
+ workspaceScopePrefs.putBoolean(key, value);\r
+ }\r
+ \r
+ m = include_pattern.matcher(name);\r
+ if ( m.matches() ) {\r
+ String fileExt = m.group(1);\r
+ Format format = ctx.eep.getFormatByExt(fileExt);\r
+ Boolean value = (Boolean) rao.getFieldValue(i, Bindings.BOOLEAN);\r
+ String key = format.id()+"_include_attachments";\r
+ contentScopePrefs.putBoolean(key, value);\r
+ workspaceScopePrefs.putBoolean(key, value);\r
+ }\r
+ \r
+ m = export_pattern.matcher(name);\r
+ if ( m.matches() ) {\r
+ String fileExt = m.group(1);\r
+ Format format = ctx.eep.getFormatByExt(fileExt);\r
+ Boolean value = (Boolean) rao.getFieldValue(i, Bindings.BOOLEAN);\r
+ String key = format.id()+"_export_attachments";\r
+ contentScopePrefs.putBoolean(key, value);\r
+ workspaceScopePrefs.putBoolean(key, value);\r
+ }\r
+ }\r
+ }\r
+ \r
+ } catch (AccessorConstructionException e) {\r
+ throw new ExportException(e);\r
+ } catch (AccessorException e) {\r
+ throw new ExportException(e);\r
+ }\r
+ \r
+ }\r
+\r
+ /**\r
+ * Load wizard preferences\r
+ * \r
+ * @param binding\r
+ * @param options\r
+ * @param contentScopePrefs\r
+ * @param workspaceScopePrefs\r
+ * @throws ExportException\r
+ */\r
+ void loadPref(Variant options, Preferences contentScopePrefs, Preferences workspaceScopePrefs) throws ExportException\r
+ {\r
+ //Preferences workspaceScopePrefs = ctx.store;\r
+ try {\r
+ RecordAccessor ra = Accessors.getAccessor(options); \r
+ String publisherId = workspaceScopePrefs.get("publisherId", "");\r
+ Publisher publisher = ctx.eep.getPublisher(publisherId);\r
+ if ( publisher != null ) ExporterUtils.setUnionValue(ra, P_PUBLISH, publisher.label());\r
+ \r
+ if ( ra.type().hasComponent(P_OUTPUT_OPTIONS.label) ) {\r
+ RecordAccessor rao = ra.getComponent( P_OUTPUT_OPTIONS );\r
+ \r
+ for (Format format : ctx.eep.formats()) {\r
+ if ( format.isGroupFormat() ) {\r
+ String key = format.id()+"_merge";\r
+ Boolean value = null;\r
+ if ( containsKey(contentScopePrefs, key) ) {\r
+ value = contentScopePrefs.getBoolean(key, false); \r
+ } else if ( containsKey(workspaceScopePrefs, key) ) {\r
+ value = workspaceScopePrefs.getBoolean(key, false);\r
+ }\r
+ \r
+ if ( value != null ) {\r
+ String key2 = "Merge "+format.fileext()+" content into one file";\r
+ int index = rao.type().getComponentIndex2(key2);\r
+ if ( index>=0 ) {\r
+ rao.setFieldValue(index, Bindings.BOOLEAN, value);\r
+ }\r
+ } \r
+ }\r
+ \r
+ if ( format.isContainerFormat() ) {\r
+ String key = format.id()+"_include_attachments";\r
+ Boolean value = null;\r
+ if ( containsKey(contentScopePrefs, key) ) {\r
+ value = contentScopePrefs.getBoolean(key, false); \r
+ } else if ( containsKey(workspaceScopePrefs, key) ) {\r
+ value = workspaceScopePrefs.getBoolean(key, false);\r
+ }\r
+ \r
+ if ( value != null ) {\r
+ String key2 = "Include attachments to "+format.fileext();\r
+ int index = rao.type().getComponentIndex2(key2);\r
+ if ( index>=0 ) {\r
+ rao.setFieldValue(index, Bindings.BOOLEAN, value);\r
+ }\r
+ } \r
+ }\r
+ \r
+ if ( format.isContainerFormat() ) {\r
+ String key = format.id()+"_export_attachments";\r
+ Boolean value = null;\r
+ if ( containsKey(contentScopePrefs, key) ) {\r
+ value = contentScopePrefs.getBoolean(key, false); \r
+ } else if ( containsKey(workspaceScopePrefs, key) ) {\r
+ value = workspaceScopePrefs.getBoolean(key, false);\r
+ }\r
+ \r
+ if ( value != null ) {\r
+ String key2 = "Export attachments of "+format.fileext()+" to separate files";\r
+ int index = rao.type().getComponentIndex2(key2);\r
+ if ( index>=0 ) {\r
+ rao.setFieldValue(index, Bindings.BOOLEAN, value);\r
+ }\r
+ } \r
+ }\r
+ \r
+ }\r
+ }\r
+ \r
+ } catch (AccessorConstructionException e) {\r
+ throw new ExportException(e);\r
+ } catch (AccessorException e) {\r
+ throw new ExportException(e);\r
+ } \r
+ }\r
+ \r
+ /**\r
+ * Save selections from previous form\r
+ */\r
+ public void savePrefs() throws ExportException {\r
+ try {\r
+ int oldSelectionHash = selectionHash; \r
+ Preferences contentScopePrefs = ctx.store.node( "Selection-"+oldSelectionHash );\r
+ Preferences workspaceScopePrefs = ctx.store;\r
+ \r
+ RecordBinding binding = ctx.databoard.getMutableBinding( form.type() );\r
+ Object obj = binding.createDefault();\r
+ Variant options = new Variant(binding, obj);\r
+ form.readFields(composite, binding, obj);\r
+ \r
+ Combo publishTo = (Combo) form.getControl(composite, P_PUBLISH); \r
+ String publisherLabel = publishTo==null?null:publishTo.getText();\r
+ if ( publisherLabel != null ) {\r
+ Publisher publisher = ctx.eep.getPublisherByLabel( publisherLabel );\r
+ if ( publisher!=null ) {\r
+ try {\r
+ ChildReference locationOptionsRef = new LabelReference(publisher.label());\r
+ Variant locationOptions = options.getComponent( locationOptionsRef );\r
+ publisher.publisherClass().savePref(locationOptions, contentScopePrefs, workspaceScopePrefs);\r
+ } catch ( AccessorConstructionException e ) {} \r
+ }\r
+ }\r
+ \r
+ for (Exporter exporter : ctx.eep.exporters()) {\r
+ exporter.exportAction().savePref(options, contentScopePrefs, workspaceScopePrefs);\r
+ }\r
+ \r
+ for (Format format : ctx.eep.formats()) {\r
+ format.formatActions().savePref(options, contentScopePrefs, workspaceScopePrefs);\r
+ } \r
+ \r
+ savePref(options, contentScopePrefs, workspaceScopePrefs);\r
+ } catch (BindingException e) {\r
+ throw new ExportException( e ); \r
+ } catch (AccessorConstructionException e) {\r
+ throw new ExportException( e ); \r
+ } catch (AccessorException e) {\r
+ throw new ExportException( e ); \r
+ } catch (ExportException e) {\r
+ throw new ExportException( e ); \r
+ }\r
+ }\r
+\r
+ public void fillDefaultPrefs(Variant options) throws ExportException {\r
+ try {\r
+ RecordAccessor ra = Accessors.getAccessor(options);\r
+\r
+ if ( ra.type().hasComponent(P_OUTPUT_OPTIONS.label) ) {\r
+ RecordAccessor rao = ra.getComponent( P_OUTPUT_OPTIONS );\r
+ \r
+ for (Format format : ctx.eep.formats()) {\r
+ if ( format.isContainerFormat() ) {\r
+ String key = "Include attachments to "+format.fileext();\r
+ int index = rao.type().getComponentIndex2(key);\r
+ if ( index>=0 ) rao.setFieldValue(index, Bindings.BOOLEAN, true);\r
+ \r
+ key = "Export attachments of "+format.fileext()+" to separate files";;\r
+ index = rao.type().getComponentIndex2(key);\r
+ if ( index>=0 ) rao.setFieldValue(index, Bindings.BOOLEAN, true);\r
+ } \r
+ }\r
+ \r
+ }\r
+ \r
+ } catch (AccessorConstructionException e) {\r
+ throw new ExportException(e);\r
+ } catch (AccessorException e) {\r
+ throw new ExportException(e);\r
+ }\r
+ } \r
+ \r
+ static boolean containsKey(Preferences pref, String key) {\r
+ try {\r
+ for (String x : pref.keys()) if ( x.equals(key) ) return true;\r
+ } catch (BackingStoreException e) {\r
+ e.printStackTrace();\r
+ } \r
+ return false; \r
+ }\r
+ \r
+}\r