com.bdaum.zoom.operations.internal.MoveOperation.java Source code

Java tutorial

Introduction

Here is the source code for com.bdaum.zoom.operations.internal.MoveOperation.java

Source

/*
 * This file is part of the ZoRa project: http://www.photozora.org.
 *
 * ZoRa is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * ZoRa is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with ZoRa; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * (c) 2009-2015 Berthold Daum  
 */

package com.bdaum.zoom.operations.internal;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.osgi.util.NLS;

import com.bdaum.zoom.cat.model.artworkOrObjectShown.ArtworkOrObjectImpl;
import com.bdaum.zoom.cat.model.artworkOrObjectShown.ArtworkOrObjectShownImpl;
import com.bdaum.zoom.cat.model.asset.Asset;
import com.bdaum.zoom.cat.model.asset.AssetImpl;
import com.bdaum.zoom.cat.model.creatorsContact.ContactImpl;
import com.bdaum.zoom.cat.model.creatorsContact.CreatorsContactImpl;
import com.bdaum.zoom.cat.model.location.LocationImpl;
import com.bdaum.zoom.cat.model.locationCreated.LocationCreatedImpl;
import com.bdaum.zoom.cat.model.locationShown.LocationShownImpl;
import com.bdaum.zoom.cat.model.meta.Meta;
import com.bdaum.zoom.core.Core;
import com.bdaum.zoom.core.IRelationDetector;
import com.bdaum.zoom.core.IVolumeManager;
import com.bdaum.zoom.core.QueryField;
import com.bdaum.zoom.core.Ticketbox;
import com.bdaum.zoom.core.db.IDbErrorHandler;
import com.bdaum.zoom.core.internal.CoreActivator;
import com.bdaum.zoom.core.internal.FileWatchManager;
import com.bdaum.zoom.core.internal.Utilities;
import com.bdaum.zoom.core.internal.db.AssetEnsemble;
import com.bdaum.zoom.core.internal.peer.AssetOrigin;
import com.bdaum.zoom.core.internal.peer.ConnectionLostException;
import com.bdaum.zoom.core.internal.peer.FileInfo;
import com.bdaum.zoom.core.internal.peer.IPeerService;
import com.bdaum.zoom.core.trash.FileLocationBackup;
import com.bdaum.zoom.operations.DbOperation;
import com.bdaum.zoom.operations.IProfiledOperation;
import com.bdaum.zoom.program.DiskFullException;

@SuppressWarnings("restriction")
public class MoveOperation extends DbOperation {

    private static final int OVERWRITE = 0;
    private static final int IGNORE = 1;
    private static final int RENAME = 2;
    private static final int CANCEL = 3;
    private List<Asset> assets;
    private File folder;
    private boolean ignoreAll;
    private boolean overwriteAll;
    private boolean renameAll;
    protected FileWatchManager fileWatchManager = CoreActivator.getDefault().getFileWatchManager();
    private Date now;
    private final GregorianCalendar cal = new GregorianCalendar();
    protected Date previousImport;

    public MoveOperation(List<Asset> assets, File folder) {
        super(Messages.getString("MoveOperation.Move_to_folder")); //$NON-NLS-1$
        this.assets = assets;
        this.folder = folder;
    }

    @Override
    public IStatus execute(final IProgressMonitor aMonitor, final IAdaptable info) throws ExecutionException {
        for (IRelationDetector detector : info.getAdapter(IRelationDetector[].class))
            detector.reset();
        init(aMonitor, assets.size() + 2);
        IVolumeManager volumeManager = Core.getCore().getVolumeManager();
        try (Ticketbox box = new Ticketbox()) {
            for (Asset asset : assets) {
                if (asset.getFileState() == IVolumeManager.PEER) {
                    AssetOrigin assetOrigin = null;
                    String assetId = asset.getStringId();
                    if (peerService != null)
                        assetOrigin = peerService.getAssetOrigin(assetId);
                    FileInfo fileInfo = null;
                    if (assetOrigin != null) {
                        try {
                            fileInfo = peerService.getFileInfo(assetOrigin, asset.getUri(), asset.getVolume());
                            if (fileInfo != null) {
                                final FileLocationBackup backup = new FileLocationBackup(opId, assetId, null, false,
                                        true);
                                File newFile = copyRemoteFile(aMonitor, asset, assetOrigin, fileInfo, info,
                                        fileWatchManager);
                                if (newFile == null) {
                                    newFile = fileInfo.getFile();
                                    backup.setFileMoved(false);
                                }
                                final List<Object> toBeStored = new ArrayList<Object>();
                                copyRemoteAsset(asset, assetOrigin, toBeStored, fileInfo, newFile, backup);
                                toBeStored.add(backup);
                                if (!storeSafely(() -> {
                                    dbManager.storeTrash(backup);
                                    for (Object o : toBeStored)
                                        dbManager.store(o);
                                }, 1))
                                    return close(info);
                                dbManager.createFolderHierarchy(asset);
                            } else
                                box.addErrand(asset.getUri(), assetOrigin.toString());
                        } catch (ConnectionLostException e) {
                            box.addErrand(asset.getUri(), assetOrigin.toString());
                        }
                    } else
                        box.addErrand(asset.getUri(), null);
                } else {
                    final URI file = volumeManager.findFile(asset);
                    if (file != null) {
                        if (volumeManager.findExistingFile(asset, true) != null) {
                            dbManager.markSystemCollectionsForPurge(asset);
                            final List<Object> toBeStored = new ArrayList<Object>(1);
                            final List<Object> toBeTrashed = new ArrayList<Object>(1);
                            moveAsset(box, asset, file, asset.getVolume(), folder, info, aMonitor, fileWatchManager,
                                    toBeStored, toBeTrashed);
                            if (!storeSafely(new Runnable() {
                                public void run() {
                                    for (Object o : toBeTrashed)
                                        dbManager.storeTrash(o);
                                    for (Object o : toBeStored)
                                        dbManager.store(o);
                                }
                            }, 1))
                                return close(info);
                            IRelationDetector[] detectors = info.getAdapter(IRelationDetector[].class);
                            for (IRelationDetector detector : detectors)
                                try {
                                    if (detector.moveAsset(asset, new File(file), new File(new URI(asset.getUri())),
                                            info, opId))
                                        break;
                                } catch (URISyntaxException e) {
                                    break;
                                }
                            dbManager.createFolderHierarchy(asset);
                        } else {
                            box.addErrand(asset.getUri(), asset.getVolume());
                            if (aMonitor.isCanceled())
                                return abort();
                        }
                    }
                }
            }
            String errorMessage = box.getErrorMessage();
            if (errorMessage != null) {
                final IDbErrorHandler errorHandler = Core.getCore().getErrorHandler();
                if (errorHandler != null)
                    errorHandler.showInformation(Messages.getString("MoveOperation.Unable_to_move"), //$NON-NLS-1$
                            errorMessage, info);
            }
        } finally {
            fileWatchManager.stopIgnoring(opId);
        }
        fireAssetsModified(null, null);
        fireStructureModified();
        assets = null;
        return close(info);
    }

    private File copyRemoteFile(final IProgressMonitor aMonitor, Asset movedAsset, AssetOrigin assetOrigin,
            FileInfo fileInfo, IAdaptable info, FileWatchManager fwManager) throws ConnectionLostException {
        try {
            File file = fileInfo.getFile();
            String fileName = file.getName();
            File newFile = new File(folder, fileName);
            String remoteHost = assetOrigin.getHost();
            String localHost = peerService.getHost();
            if (remoteHost.equals(localHost) && file.equals(newFile))
                return newFile;
            if (newFile.exists()) {
                if (newFile.exists()) {
                    switch (promptForOverwrite(newFile, info)) {
                    case IGNORE:
                        return null;
                    case RENAME:
                        newFile = makeUnique(newFile);
                        break;
                    case OVERWRITE:
                        newFile.delete();
                        break;
                    default:
                        aMonitor.setCanceled(true);
                        return null;
                    }
                }
            }
            SubMonitor sub = SubMonitor.convert(aMonitor, 1);
            fileWatchManager.ignore(newFile, opId);
            URI uri = file.toURI();
            peerService.transferRemoteFile(sub, assetOrigin, fileInfo, newFile);
            File[] xmpOrigs = Core.getSidecarFiles(uri, false);
            URI newURI = newFile.toURI();
            File[] xmpTargets = Core.getSidecarFiles(newURI, false);
            String volume = movedAsset.getVolume();
            long modmax = -1;
            for (int i = 0; i < xmpOrigs.length; i++) {
                File xmpTarget = xmpTargets[i];
                xmpTarget.delete();
                fileWatchManager.ignore(xmpTarget, opId);
                sub = SubMonitor.convert(aMonitor, 1);
                FileInfo xmpInfo = peerService.getFileInfo(assetOrigin, xmpOrigs[i].toString(), volume);
                peerService.transferRemoteFile(sub, assetOrigin, xmpInfo, xmpTarget);
                modmax = Math.max(modmax, xmpTarget.lastModified());
            }
            movedAsset.setXmpModifiedAt(modmax < 0 ? null : new Date(modmax));
            if (peerService.checkCredentials(IPeerService.VOICE, movedAsset.getSafety(), assetOrigin)) {
                String voiceOrigURI = null;
                URI voiceTargetURI = null;
                if (AssetEnsemble.hasCloseVoiceNote(movedAsset)) {
                    URI u = Core.getVoicefileURI(file);
                    voiceOrigURI = u == null ? null : u.toString();
                    voiceTargetURI = Core.getVoicefileURI(newFile);
                } else {
                    voiceOrigURI = AssetEnsemble.extractVoiceNote(movedAsset);
                    volume = movedAsset.getVoiceVolume();
                }
                if (voiceOrigURI != null) {
                    File voiceTarget = null;
                    voiceTarget = new File(voiceTargetURI);
                    voiceTarget.delete();
                    fileWatchManager.ignore(voiceTarget, opId);
                    sub = SubMonitor.convert(aMonitor, 1);
                    FileInfo voiceInfo = peerService.getFileInfo(assetOrigin, voiceOrigURI, volume);
                    peerService.transferRemoteFile(sub, assetOrigin, voiceInfo, voiceTarget);
                    AssetEnsemble.insertVoiceNote(movedAsset, movedAsset.getVolume(), "."); //$NON-NLS-1$
                } else
                    AssetEnsemble.insertVoiceNote(movedAsset, null, null);
            } else
                AssetEnsemble.insertVoiceNote(movedAsset, null, null);
            return newFile;
        } catch (IOException e) {
            addError(NLS.bind(Messages.getString("MoveOperation.io_error_remote_file"), //$NON-NLS-1$
                    fileInfo.getFile()), e);
        } catch (DiskFullException e) {
            addError(NLS.bind(Messages.getString("MoveOperation.Moving_of_image_failed"), fileInfo.getFile()), e); //$NON-NLS-1$
        }
        return null;
    }

    private void copyRemoteAsset(Asset movedAsset, AssetOrigin assetOrigin, List<Object> toBeStored,
            FileInfo fileInfo, File newFile, FileLocationBackup backup) throws ConnectionLostException {
        if (now == null) {
            now = new Date();
            createLastImport();
        }
        AssetImpl asset = new AssetImpl();
        AssetEnsemble.transferAssetData(movedAsset, asset, null);
        asset.setUri(newFile.toURI().toString());
        asset.setVolume(Core.getCore().getVolumeManager().getVolumeForFile(newFile));
        asset.setImportDate(now);
        asset.setImportedBy(System.getProperty("user.name")); //$NON-NLS-1$
        asset.setFileState(IVolumeManager.ONLINE);
        asset.setLastEditor(null);
        String assetId = asset.getStringId();
        toBeStored.add(asset);
        String relId = asset.getCreatorsContact_parent();
        if (relId != null) {
            Iterator<CreatorsContactImpl> it = peerService
                    .obtainStructForAsset(assetOrigin, CreatorsContactImpl.class, assetId, true).iterator();
            if (it.hasNext()) {
                CreatorsContactImpl rel = it.next();
                String contactId = rel.getContact();
                if (contactId == null)
                    asset.setCreatorsContact_parent(null);
                else {
                    ContactImpl contact = peerService.obtainById(assetOrigin, ContactImpl.class, contactId);
                    if (contact == null)
                        asset.setCreatorsContact_parent(null);
                    else {
                        Iterator<ContactImpl> cit = dbManager.queryByExample(contact).iterator();
                        if (cit.hasNext()) {
                            contact = cit.next();
                            Iterator<CreatorsContactImpl> itcc = dbManager
                                    .obtainObjects(CreatorsContactImpl.class, "contact", //$NON-NLS-1$
                                            contact.getStringId(), QueryField.EQUALS)
                                    .iterator();
                            if (itcc.hasNext())
                                rel = itcc.next();
                            else
                                rel.setContact(contactId);
                        } else {
                            toBeStored.add(contact);
                            backup.addCreatedObject(contact);
                        }
                        rel.getAsset().clear();
                        rel.addAsset(assetId);
                        toBeStored.add(rel);
                    }
                }
            } else
                asset.setCreatorsContact_parent(null);
        }
        relId = asset.getLocationCreated_parent();
        if (relId != null) {
            Iterator<LocationCreatedImpl> it = peerService
                    .obtainStructForAsset(assetOrigin, LocationCreatedImpl.class, assetId, true).iterator();
            if (it.hasNext()) {
                LocationCreatedImpl rel = it.next();
                rel.getAsset().clear();
                String locationId = rel.getLocation();
                if (locationId == null)
                    asset.setLocationCreated_parent(null);
                else {
                    LocationImpl location = peerService.obtainById(assetOrigin, LocationImpl.class, locationId);
                    if (location == null)
                        asset.setLocationCreated_parent(null);
                    else {
                        Iterator<LocationImpl> cit = dbManager.queryByExample(location).iterator();
                        if (cit.hasNext()) {
                            location = cit.next();
                            Iterator<LocationCreatedImpl> itlc = dbManager
                                    .obtainObjects(LocationCreatedImpl.class, "location", //$NON-NLS-1$
                                            location.getStringId(), QueryField.EQUALS)
                                    .iterator();
                            if (itlc.hasNext())
                                rel = itlc.next();
                            else
                                rel.setLocation(locationId);
                        } else {
                            toBeStored.add(location);
                            backup.addCreatedObject(location);
                        }
                        rel.addAsset(assetId);
                        toBeStored.add(rel);
                    }
                }
            } else
                asset.setLocationCreated_parent(null);
        }
        List<String> relIds = asset.getLocationShown_parent();
        if (!relIds.isEmpty()) {
            Iterator<LocationShownImpl> it = peerService
                    .obtainStructForAsset(assetOrigin, LocationShownImpl.class, assetId, true).iterator();
            if (it.hasNext()) {
                while (it.hasNext()) {
                    LocationShownImpl r = it.next();
                    LocationImpl location = peerService.obtainById(assetOrigin, LocationImpl.class,
                            r.getStringId());
                    if (location == null)
                        relIds.remove(r.getStringId());
                    else {
                        Iterator<LocationImpl> cit = dbManager.queryByExample(location).iterator();
                        if (cit.hasNext()) {
                            location = cit.next();
                            r.setLocation(location.getStringId());
                        } else {
                            toBeStored.add(location);
                            backup.addCreatedObject(location);
                        }
                        r.setAsset(assetId);
                        toBeStored.add(r);
                    }
                }
            } else
                relIds.clear();
        }
        relIds = asset.getArtworkOrObjectShown_parent();
        if (!relIds.isEmpty()) {
            List<ArtworkOrObjectShownImpl> set = peerService.obtainStructForAsset(assetOrigin,
                    ArtworkOrObjectShownImpl.class, assetId, true);
            if (set.isEmpty())
                relIds.clear();
            else {
                for (ArtworkOrObjectShownImpl r : set) {
                    ArtworkOrObjectImpl artwork = peerService.obtainById(assetOrigin, ArtworkOrObjectImpl.class,
                            r.getStringId());
                    if (artwork == null)
                        relIds.remove(r.getStringId());
                    else {
                        Iterator<ArtworkOrObjectImpl> ita = dbManager.queryByExample(artwork).iterator();
                        if (ita.hasNext()) {
                            artwork = ita.next();
                            r.setArtworkOrObject(artwork.getStringId());
                        } else {
                            toBeStored.add(artwork);
                            backup.addCreatedObject(artwork);
                        }
                        r.setAsset(assetId);
                        toBeStored.add(r);
                    }
                }
            }
        }
    }

    private void createLastImport() {
        final Meta meta = dbManager.getMeta(true);
        cal.setTime(meta.getLastImport());
        int year = cal.get(Calendar.YEAR);
        meta.setLastImport(now);
        cal.setTime(now);
        if (year != cal.get(Calendar.YEAR))
            meta.setLastYearSequenceNo(0);
        if (storeSafely(() -> {
            previousImport = dbManager.createLastImportCollection(now, false,
                    Messages.getString("MoveOperation.import_caused"), false); //$NON-NLS-1$
            dbManager.store(meta);
        }, 1))
            fireStructureModified();
    }

    private void moveAsset(Ticketbox box, Asset movedAsset, URI uri, String volume, File target, IAdaptable info,
            IProgressMonitor aMonitor, FileWatchManager fwManager, List<Object> toBeStored,
            List<Object> toBeTrashed) {
        File file = null;
        if (uri != null) {
            try {
                file = box.obtainFile(uri);
            } catch (IOException e) {
                box.addErrand(uri.toString(), volume);
            }
        }
        String assetId = movedAsset.getStringId();
        if (file != null) {
            Path path = new Path(file.getAbsolutePath());
            toBeTrashed.add(new FileLocationBackup(opId, assetId, box.isLocal() ? path : null, true, false));
            Path folderPath = new Path(target.getAbsolutePath());
            IPath newPath = folderPath.append(path.lastSegment());
            if (!newPath.equals(path)) {
                File newFile = newPath.toFile();
                if (newFile.exists()) {
                    switch (promptForOverwrite(newFile, info)) {
                    case IGNORE:
                        return;
                    case RENAME:
                        newFile = makeUnique(newFile);
                        break;
                    case OVERWRITE:
                        newFile.delete();
                        break;
                    default:
                        aMonitor.setCanceled(true);
                        return;
                    }
                }
                File[] xmpOrigs = Core.getSidecarFiles(uri, false);
                URI newURI = newFile.toURI();
                File[] xmpTargets = Core.getSidecarFiles(newURI, false);
                URI voiceOrigURI = null;
                URI voiceTargetURI = null;
                if (AssetEnsemble.hasCloseVoiceNote(movedAsset)) {
                    voiceOrigURI = Core.getVoicefileURI(file);
                    voiceTargetURI = Core.getVoicefileURI(newFile);
                }
                try {
                    fwManager.moveFileSilently(file, newFile, opId, aMonitor);
                    movedAsset.setUri(newURI.toString());
                    toBeStored.add(movedAsset);
                    for (int i = 0; i < xmpOrigs.length; i++) {
                        File xmpFile = xmpOrigs[i];
                        File xmpTarget = null;
                        if (xmpFile.exists()) {
                            xmpTarget = xmpTargets[i];
                            xmpTarget.delete();
                            fwManager.moveFileSilently(xmpFile, xmpTarget, opId, aMonitor);
                        }
                    }
                    if (voiceOrigURI != null) {
                        File voiceFile = new File(voiceOrigURI);
                        File voiceTarget = null;
                        if (voiceFile.exists()) {
                            voiceTarget = new File(voiceTargetURI);
                            voiceTarget.delete();
                            fwManager.moveFileSilently(voiceFile, voiceTarget, opId, aMonitor);
                        }
                    }
                } catch (IOException e) {
                    addError(NLS.bind(Messages.getString("MoveOperation.Moving_of_image_failed"), file), e); //$NON-NLS-1$
                } catch (DiskFullException e) {
                    addError(NLS.bind(Messages.getString("MoveOperation.Moving_of_image_failed"), file), e); //$NON-NLS-1$
                }
            }
        } else
            toBeTrashed.add(new FileLocationBackup(opId, assetId, null, true, false));
    }

    private int promptForOverwrite(File newFile, IAdaptable info) {
        if (ignoreAll)
            return IGNORE;
        if (renameAll)
            return RENAME;
        if (overwriteAll)
            return OVERWRITE;
        int ret = 6;
        IDbErrorHandler errorHandler = Core.getCore().getErrorHandler();
        if (errorHandler != null)
            ret = errorHandler.showMessageDialog(Messages.getString("MoveOperation.Same_file_exists"), //$NON-NLS-1$
                    null, NLS.bind(Messages.getString("MoveOperation.File_already_exists"), //$NON-NLS-1$
                            newFile.getName()),
                    MessageDialog.QUESTION, new String[] { Messages.getString("MoveOperation.Overwrite"), //$NON-NLS-1$
                            Messages.getString("MoveOperation.Overwrite_all"), IDialogConstants.SKIP_LABEL, //$NON-NLS-1$
                            Messages.getString("MoveOperation.Skip_all"), //$NON-NLS-1$
                            Messages.getString("MoveOperation.Rename"), //$NON-NLS-1$
                            Messages.getString("MoveOperation.Rename_all"), //$NON-NLS-1$
                            IDialogConstants.CANCEL_LABEL },
                    0, info);
        switch (ret) {
        case 1:
            overwriteAll = true;
            //$FALL-THROUGH$
        case 0:
            return OVERWRITE;
        case 3:
            ignoreAll = true;
            //$FALL-THROUGH$
        case 2:
            return IGNORE;
        case 5:
            renameAll = true;
            //$FALL-THROUGH$
        case 4:
            return RENAME;
        default:
            return CANCEL;
        }
    }

    private static File makeUnique(File file) {
        String path = file.getAbsolutePath();
        int q = path.lastIndexOf('/');
        int p = path.lastIndexOf('.');
        String ext = ""; //$NON-NLS-1$
        if (p > q) {
            ext = path.substring(p);
            path = path.substring(0, p);
        }
        int i = 0;
        while (true) {
            File newFile = new File(path + "-" + (++i) + ext); //$NON-NLS-1$
            if (!newFile.exists())
                return newFile;
        }
    }

    @Override
    public boolean canRedo() {
        return false;
    }

    @Override
    public IStatus redo(IProgressMonitor aMonitor, IAdaptable info) throws ExecutionException {
        return null;
    }

    @Override
    public IStatus undo(final IProgressMonitor aMonitor, IAdaptable info) throws ExecutionException {
        boolean changed = false;
        final List<Object> toBeStored = new ArrayList<Object>();
        final Set<Object> toBeDeleted = new HashSet<Object>();
        try {
            List<FileLocationBackup> set = dbManager.getTrash(FileLocationBackup.class, opId);
            initUndo(aMonitor, set.size());
            for (FileLocationBackup backup : set) {
                toBeDeleted.clear();
                toBeStored.clear();
                Asset asset = backup.restore(dbManager, opId, aMonitor, toBeStored, toBeDeleted);
                final FileLocationBackup t = backup;
                if (storeSafely(() -> {
                    dbManager.deleteTrash(t);
                    for (Object o1 : toBeDeleted)
                        dbManager.delete(o1);
                    for (Object o2 : toBeStored)
                        dbManager.store(o2);
                }, 1) && asset != null)
                    changed |= dbManager.createFolderHierarchy(asset);
            }
            fireAssetsModified(null, null);
        } finally {
            fileWatchManager.stopIgnoring(opId);
            if (now != null) {
                toBeDeleted.clear();
                toBeStored.clear();
                Utilities.popLastImport(toBeStored, toBeDeleted, previousImport, true);
                storeSafely(toBeDeleted.toArray(), 1, toBeStored.toArray());
                changed = true;
            }
            if (changed)
                fireStructureModified();
        }
        return close(info);
    }

    public int getExecuteProfile() {
        return IProfiledOperation.CONTENT | IProfiledOperation.FILE;
    }

    public int getUndoProfile() {
        return IProfiledOperation.CONTENT | IProfiledOperation.FILE;
    }

    @Override
    public int getPriority() {
        return assets.size() > 3 ? Job.LONG : Job.SHORT;
    }

    protected void handleResume(Meta meta, int code, int i, IAdaptable info) {
        // do nothing
    }

}