package org.simantics.export.core.impl; import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.eclipse.core.runtime.IProgressMonitor; import org.osgi.service.prefs.Preferences; import org.simantics.databoard.Accessors; import org.simantics.databoard.Bindings; import org.simantics.databoard.Datatypes; import org.simantics.databoard.accessor.RecordAccessor; import org.simantics.databoard.accessor.error.AccessorConstructionException; import org.simantics.databoard.accessor.error.AccessorException; import org.simantics.databoard.accessor.reference.ChildReference; import org.simantics.databoard.accessor.reference.LabelReference; import org.simantics.databoard.binding.mutable.Variant; import org.simantics.databoard.forms.DataboardForm; import org.simantics.databoard.type.Datatype; import org.simantics.databoard.type.RecordType; import org.simantics.databoard.type.StringType; import org.simantics.export.core.ExportContext; import org.simantics.export.core.error.ExportException; import org.simantics.export.core.intf.Format; import org.simantics.export.core.intf.PublisherClass; import org.simantics.export.core.manager.Content; import org.simantics.export.core.util.ExporterUtils; import org.simantics.utils.datastructures.collections.CollectionUtils; /** * There is one output field for each content: * [ ] Overwrite file(s) * file1.ext [________________________] (Select) * file2.ext [________________________] (Select) * ... * fileN.ext [________________________] (Select) * * @author toni.kalajainen@semantum.fi */ public class FilePublisher implements PublisherClass { public static LabelReference P_ALLOW_OVERWRITE = new LabelReference("Overwrite file(s)"); @Override public void publish(ExportContext ctx, List contents, Variant options, Variant locationOptions, IProgressMonitor monitor) throws ExportException { Boolean canOverwrite = ExporterUtils.getBoolean(locationOptions, P_ALLOW_OVERWRITE); for ( Content content : contents ) { if ( content.tmpFile == null ) throw new ExportException("Internal error, tmpFile was null for "+content.label+content.formatExt ); String filePath = ExporterUtils.getString( locationOptions, new LabelReference( content.filename ) ); filePath = PublisherUtil.ensureEndsWith(true, content.formatExt, filePath); File file = new File( filePath ); if ( file.exists() ) { if ( canOverwrite ) { file.delete(); } else { throw new ExportException("Would not overwrite " + file.getAbsolutePath()); } } content.tmpFile.renameTo(file); } } @Override public List validate(ExportContext ctx, List contents, Variant options, Variant locationOptions) throws ExportException { List result = new ArrayList(); Boolean canOverwrite = ExporterUtils.getBoolean(locationOptions, P_ALLOW_OVERWRITE); if ( canOverwrite == null ) { result.add("CanOverwrite option missing?"); return result; } List missingPaths = new ArrayList(); for ( Content content : contents ) { String filePath = ExporterUtils.getString( locationOptions, new LabelReference( content.filename ) ); if ( filePath == null || filePath.isEmpty() ) { missingPaths.add( content.filename ); } else { filePath = PublisherUtil.ensureEndsWith(true, content.formatExt, filePath); File file = new File( filePath ); if ( !canOverwrite && file.exists() ) { result.add(file.getAbsolutePath()+" already exists."); } } } if ( !missingPaths.isEmpty() ) { result.add(0, "Path for " + CollectionUtils.toString(missingPaths, ", ") + " is required."); } return result; } @Override public RecordType locationOptions(ExportContext ctx, List contents) throws ExportException { RecordType rt = new RecordType(); for ( Content content : contents ) { Format format = ctx.eep.getFormat( content.formatId ); rt.addComponent(content.filename, DataboardForm.fileSaveDialog( format.label(), "*"+format.fileext() ) ); } rt.addComponent(P_ALLOW_OVERWRITE.label, Datatypes.BOOLEAN); return rt; } @Override public Variant createLocation(ExportContext ctx, Variant locationOptions) throws ExportException { // Make Dirs to the path. for ( File file : readLocations(locationOptions).values() ) { File parentFile = file.getParentFile(); if ( parentFile == null ) continue; if ( parentFile.exists() && !parentFile.isDirectory() ) throw new ExportException( parentFile+" is not directory."); if ( parentFile.exists() ) continue; if (!parentFile.mkdirs()) throw new ExportException( "Failed to create "+parentFile ); } return locationOptions; } @Override public boolean locationExists(ExportContext ctx, Variant locationOptions) throws ExportException { boolean exists = true; for ( File file : readLocations(locationOptions).values() ) { File parentFile = file.getParentFile(); if ( parentFile == null ) continue; exists &= parentFile.exists() && parentFile.isDirectory(); } return exists; } @Override public void fillDefaultPrefs(ExportContext ctx, List contents, Variant options, Variant locationOptions) throws ExportException { try { RecordAccessor ra = Accessors.getAccessor(locationOptions); ra.setValue(P_ALLOW_OVERWRITE, Bindings.BOOLEAN, true); // Fill defaults using dir location and content filename :D String path = ExporterUtils.getString( options, new LabelReference("Dir", DirPublisher.P_EXPORT_LOCATION) ); if ( path != null ) { RecordType rt = ra.type(); for ( int i=0; i entry : readLocations(locationOptions).entrySet() ) { String key = entry.getKey(); String value = ExporterUtils.getPrefString(contentScopePrefs, workspaceScopePrefs, key); if ( value != null ) { ChildReference ref = new LabelReference( key ); ra.setValue( ref, Bindings.STRING, value ); } } String key = P_ALLOW_OVERWRITE.tail().toString(); Boolean b = ExporterUtils.getPrefBoolean(contentScopePrefs, workspaceScopePrefs, key); if ( b!=null ) ra.setValue(P_ALLOW_OVERWRITE, Bindings.BOOLEAN, b); } catch (AccessorConstructionException e) { throw new ExportException( e ); } catch (AccessorException e) { throw new ExportException( e ); } } Map readLocations(Variant location) throws ExportException { HashMap result = new HashMap(); try { RecordAccessor ra = Accessors.getAccessor(location); RecordType rt = (RecordType) location.type(); for (int i=0; i