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

Java tutorial

Introduction

Here is the source code for com.bdaum.zoom.operations.internal.MigrateOperation.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) 2016 Berthold Daum  
 */
package com.bdaum.zoom.operations.internal;

import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.osgi.util.NLS;

import com.bdaum.aoModeling.runtime.AomList;
import com.bdaum.zoom.cat.model.BookmarkImpl;
import com.bdaum.zoom.cat.model.Ghost_typeImpl;
import com.bdaum.zoom.cat.model.MigrationPolicy;
import com.bdaum.zoom.cat.model.MigrationPolicy_type;
import com.bdaum.zoom.cat.model.MigrationRule;
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.asset.MediaExtension;
import com.bdaum.zoom.cat.model.asset.RegionImpl;
import com.bdaum.zoom.cat.model.asset.TrackRecordImpl;
import com.bdaum.zoom.cat.model.composedTo.ComposedToImpl;
import com.bdaum.zoom.cat.model.creatorsContact.ContactImpl;
import com.bdaum.zoom.cat.model.creatorsContact.CreatorsContactImpl;
import com.bdaum.zoom.cat.model.derivedBy.DerivedByImpl;
import com.bdaum.zoom.cat.model.group.Criterion;
import com.bdaum.zoom.cat.model.group.CriterionImpl;
import com.bdaum.zoom.cat.model.group.Group;
import com.bdaum.zoom.cat.model.group.GroupImpl;
import com.bdaum.zoom.cat.model.group.PostProcessor;
import com.bdaum.zoom.cat.model.group.SmartCollection;
import com.bdaum.zoom.cat.model.group.SmartCollectionImpl;
import com.bdaum.zoom.cat.model.group.SortCriterion;
import com.bdaum.zoom.cat.model.group.SortCriterionImpl;
import com.bdaum.zoom.cat.model.group.exhibition.ExhibitImpl;
import com.bdaum.zoom.cat.model.group.exhibition.ExhibitionImpl;
import com.bdaum.zoom.cat.model.group.exhibition.WallImpl;
import com.bdaum.zoom.cat.model.group.slideShow.SlideImpl;
import com.bdaum.zoom.cat.model.group.slideShow.SlideShowImpl;
import com.bdaum.zoom.cat.model.group.webGallery.StoryboardImpl;
import com.bdaum.zoom.cat.model.group.webGallery.WebExhibitImpl;
import com.bdaum.zoom.cat.model.group.webGallery.WebGalleryImpl;
import com.bdaum.zoom.cat.model.group.webGallery.WebParameterImpl;
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.LastDeviceImport;
import com.bdaum.zoom.cat.model.meta.Meta;
import com.bdaum.zoom.cat.model.meta.WatchedFolder;
import com.bdaum.zoom.cat.model.pageLayout.PageLayoutImpl;
import com.bdaum.zoom.core.CatalogListener;
import com.bdaum.zoom.core.Constants;
import com.bdaum.zoom.core.Core;
import com.bdaum.zoom.core.IPostProcessor;
import com.bdaum.zoom.core.IVolumeManager;
import com.bdaum.zoom.core.QueryField;
import com.bdaum.zoom.core.db.IDbManager;
import com.bdaum.zoom.core.internal.CoreActivator;
import com.bdaum.zoom.core.internal.Utilities;
import com.bdaum.zoom.core.internal.VolumeManager;
import com.bdaum.zoom.core.internal.db.AssetEnsemble;

@SuppressWarnings("restriction")
public class MigrateOperation extends AbstractCloneCatOperation {

    private IDbManager newDbManager;
    private Pattern[] patterns;
    private IVolumeManager volumeManager;
    private Set<String> visited = new HashSet<String>();
    private MigrationRule[] rules;
    private int fileSeparatorPolicy;
    private String finalMessage;
    private int severity;
    private boolean winTarget;
    private String currentVolume;

    public MigrateOperation(IDbManager newDbManager, MigrationPolicy policy) {
        super(Messages.getString("MigrateOperation.migrate_cat")); //$NON-NLS-1$
        this.newDbManager = newDbManager;
        volumeManager = Core.getCore().getVolumeManager();
        rules = policy.getRule();
        patterns = new Pattern[rules.length];
        int flags = Constants.WIN32 ? Pattern.CASE_INSENSITIVE : 0;
        for (int i = 0; i < rules.length; i++)
            patterns[i] = Pattern.compile(rules[i].getSourcePattern(), flags);
        String fsp = policy.getFileSeparatorPolicy();
        fileSeparatorPolicy = MigrationPolicy_type.fileSeparatorPolicy_tOSLASH.equals(fsp) ? 1
                : MigrationPolicy_type.fileSeparatorPolicy_tOBACKSLASH.equals(fsp) ? 2 : 0;
        switch (fileSeparatorPolicy) {
        case 1:
            winTarget = false;
            break;
        case 2:
            winTarget = true;
            break;
        default:
            winTarget = Constants.WIN32;
        }
    }

    @Override
    public IStatus execute(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
        List<URI> failedWatchedFolders = new ArrayList<URI>();
        List<URI> watchedFoldersWithFilters = new ArrayList<URI>();
        init(monitor, 1337000);
        monitor.subTask(Messages.getString("MigrateOperation.migrating")); //$NON-NLS-1$
        try {
            final Meta oldMeta = dbManager.getMeta(true);
            Meta newMeta = newDbManager.getMeta(true);
            newMeta.setPlatform("$migrated$"); //$NON-NLS-1$
            List<Object> toBeStored = cloneMeta(newDbManager, oldMeta, newMeta, oldMeta.getDescription());
            newMeta.setKeywords(oldMeta.getKeywords());
            Utilities.ensureCatConsistency(oldMeta.getCategory());
            newMeta.setCategory(oldMeta.getCategory());
            newMeta.setCleaned(false);
            newMeta.setCreationDate(oldMeta.getCreationDate());
            newMeta.setRelevantLireVersion(oldMeta.getRelevantLireVersion());
            newMeta.setBackupLocation(migrate(oldMeta.getBackupLocation()));
            if (oldMeta.getColorLabels() != null)
                newMeta.setColorLabels(oldMeta.getColorLabels());
            newMeta.setPersonsToKeywords(oldMeta.getPersonsToKeywords());
            newMeta.setThumbnailResolution(oldMeta.getThumbnailResolution());
            newMeta.setSharpen(oldMeta.getSharpen());
            newMeta.setWebpCompression(oldMeta.getWebpCompression());
            newMeta.setJpegQuality(oldMeta.getJpegQuality());
            newMeta.setThumbnailFromPreview(oldMeta.getThumbnailFromPreview());
            newMeta.setTimeline(oldMeta.getTimeline());
            newMeta.setLocationFolders(oldMeta.getLocationFolders());
            newMeta.setPauseFolderWatch(oldMeta.getPauseFolderWatch());
            newMeta.setReadonly(false);
            newMeta.setAutoWatch(oldMeta.getAutoWatch());
            newMeta.setFolderWatchLatency(oldMeta.getFolderWatchLatency());
            newMeta.setLocale(oldMeta.getLocale());
            newMeta.setCumulateImports(oldMeta.getCumulateImports());
            newMeta.setCbirAlgorithms(CoreActivator.getDefault().getCbirAlgorithms());
            newMeta.setIndexedTextFields(CoreActivator.getDefault().getIndexedTextFields(oldMeta));
            Map<String, LastDeviceImport> lastDeviceImports = oldMeta.getLastDeviceImport();
            if (lastDeviceImports != null)
                toBeStored.addAll(lastDeviceImports.values());
            List<String> watchedFolders = oldMeta.getWatchedFolder();
            if (watchedFolders != null)
                for (String id : watchedFolders) {
                    WatchedFolder watchedFolder = dbManager.obtainById(WatchedFolder.class, id);
                    String oldUri = watchedFolder.getUri();
                    String oldVolume = watchedFolder.getVolume();
                    String oldTarget = watchedFolder.getTargetDir();
                    String source = migrateUri(oldUri, oldVolume);
                    if (source.isEmpty()) {
                        failedWatchedFolders.add(volumeManager.findFile(oldUri, oldVolume));
                        continue;
                    }
                    if (watchedFolder.getTransfer()) {
                        String target = migrate(oldTarget);
                        if (target.isEmpty()) {
                            failedWatchedFolders.add(volumeManager.findFile(oldUri, oldVolume));
                            continue;
                        }
                        watchedFolder.setTargetDir(target);
                    }
                    watchedFolder.setUri(toUri(source));
                    watchedFolder.setVolume(extractVolume(source));
                    String oldFilters = watchedFolder.getFilters();
                    if (oldFilters != null && !oldFilters.isEmpty())
                        watchedFoldersWithFilters.add(volumeManager.findFile(oldUri, oldVolume));
                    newDbManager.storeAndCommit(watchedFolder);
                    newMeta.addWatchedFolder(id);
                    watchedFolder.setUri(oldUri);
                    watchedFolder.setVolume(oldVolume);
                    watchedFolder.setTargetDir(oldTarget);
                    if (monitor.isCanceled())
                        return abort();
                }
            if (monitor.isCanceled())
                return abort();
            toBeStored.add(newMeta);
            newDbManager.safeTransaction(null, toBeStored);
            if (monitor.isCanceled())
                return abort();
            monitor.worked(1000);
            monitor.subTask(Messages.getString("MigrateOperation.migrate_groups")); //$NON-NLS-1$
            if (copyObjects(GroupImpl.class, 20000))
                return abort();
            GroupImpl folderGroup = newDbManager.obtainById(GroupImpl.class, Constants.GROUP_ID_FOLDERSTRUCTURE);
            List<Group> oldSubgroup = new ArrayList<Group>(folderGroup.getSubgroup());
            folderGroup.getSubgroup().clear();
            newDbManager.storeAndCommit(folderGroup);
            folderGroup.setSubgroup(oldSubgroup);
            if (copyObjects(ContactImpl.class, 1000))
                return abort();
            if (copyObjects(CreatorsContactImpl.class, 1000))
                return abort();
            if (copyObjects(LocationImpl.class, 1000))
                return abort();
            if (copyObjects(LocationShownImpl.class, 1000))
                return abort();
            if (copyObjects(LocationCreatedImpl.class, 1000))
                return abort();
            if (copyObjects(ArtworkOrObjectImpl.class, 1000))
                return abort();
            if (copyObjects(ArtworkOrObjectShownImpl.class, 1000))
                return abort();
            if (copyObjects(TrackRecordImpl.class, 1000))
                return abort();
            if (copyObjects(RegionImpl.class, 1000))
                return abort();
            if (copyObjects(ComposedToImpl.class, 1000))
                return abort();
            if (copyObjects(DerivedByImpl.class, 1000))
                return abort();
            int i = 0;
            List<Asset> assets = dbManager.obtainObjects(Asset.class);
            int na = assets.size();
            int work = 1000000;
            int incr = na == 0 ? work : work / na;
            for (Asset asset : assets) {
                monitor.subTask(NLS.bind(Messages.getString("MigrateOperation.migrating_image"), ++i, na)); //$NON-NLS-1$
                String oldUri = asset.getUri();
                String oldVolume = asset.getVolume();
                boolean remote = volumeManager.isRemote(asset);
                String migratedPath = migrateUri(oldUri, oldVolume);
                if (remote || !migratedPath.isEmpty()) {
                    toBeStored.clear();
                    toBeStored.add(asset);
                    String assetId = asset.getStringId();
                    String oldVoiceFileURI = asset.getVoiceFileURI();
                    String oldVoiceVolume = asset.getVoiceVolume();
                    String migratedUri = null;
                    String migratedVolume = null;
                    if (!remote) {
                        migratedUri = toUri(migratedPath);
                        asset.setUri(migratedUri);
                        migratedVolume = extractVolume(migratedPath);
                        asset.setVolume(migratedVolume);
                        String voiceUri = AssetEnsemble.extractVoiceNote(asset);
                        if (voiceUri != null) {
                            String migratedVoicePath = migrateUri(voiceUri, oldVoiceVolume);
                            AssetEnsemble.insertVoiceNote(asset, extractVolume(migratedVoicePath),
                                    migratedVoicePath.isEmpty() ? null : toUri(migratedVoicePath));
                        }
                    }
                    visited.add(assetId);
                    List<Ghost_typeImpl> ghosts = dbManager.obtainObjects(Ghost_typeImpl.class,
                            QueryField.NAME.getKey(), asset.getName(), QueryField.EQUALS);
                    for (Ghost_typeImpl ghost : ghosts)
                        if (ghost.getUri() != null && ghost.getUri().equals(oldUri) && migratedUri != null) {
                            ghost.setUri(migratedUri);
                            ghost.setVolume(migratedVolume);
                            toBeStored.add(ghost);
                        }
                    MediaExtension[] mediaExtensions = asset.getMediaExtension();
                    if (mediaExtensions != null)
                        for (MediaExtension mediaExt : mediaExtensions)
                            toBeStored.add(mediaExt);
                    newDbManager.safeTransaction(null, toBeStored);
                    newDbManager.createFolderHierarchy(asset, winTarget);
                    asset.setUri(oldUri);
                    asset.setVolume(oldVolume);
                    asset.setVoiceFileURI(oldVoiceFileURI);
                    asset.setVoiceVolume(oldVoiceVolume);
                    for (Object obj : toBeStored)
                        if (obj instanceof Ghost_typeImpl) {
                            ((Ghost_typeImpl) obj).setUri(oldUri);
                            ((Ghost_typeImpl) obj).setVolume(oldVolume);
                        }
                }
                if (monitor.isCanceled())
                    return abort();
                monitor.worked(incr);
                work -= incr;
            }
            monitor.worked(work);
            List<SmartCollectionImpl> collections = dbManager.obtainObjects(SmartCollectionImpl.class);
            work = 100000;
            na = collections.size();
            incr = na == 0 ? work : work / na;
            String uriKey = QueryField.URI.getKey() + '=';
            String volumeKey = QueryField.VOLUME.getKey() + '=';
            for (SmartCollectionImpl coll : collections) {
                if (coll.getSmartCollection_subSelection_parent() == null) {
                    String id = coll.getStringId();
                    if (!id.startsWith(uriKey) && !id.startsWith(volumeKey)) {
                        toBeStored.clear();
                        monitor.subTask(NLS.bind(Messages.getString("MigrateOperation.migrating_collections"), //$NON-NLS-1$
                                coll.getName()));
                        transferSmartCollection(toBeStored, coll, null);
                        newDbManager.safeTransaction(null, toBeStored);
                        if (monitor.isCanceled())
                            return abort();
                    }
                }
                monitor.worked(incr);
                work -= incr;
            }
            monitor.worked(work);
            monitor.subTask(Messages.getString("MigrateOperation.migrating_presentations")); //$NON-NLS-1$
            if (copyObjects(SlideShowImpl.class, 5000))
                return abort();
            if (copyObjects(SlideImpl.class, 50000))
                return abort();
            if (copyObjects(ExhibitImpl.class, 50000))
                return abort();
            if (copyObjects(WallImpl.class, 5000))
                return abort();
            List<ExhibitionImpl> exhibitions = dbManager.obtainObjects(ExhibitionImpl.class);
            work = 5000;
            na = exhibitions.size();
            incr = na == 0 ? work : work / na;
            for (ExhibitionImpl exhibition : exhibitions) {
                String oldFolder = exhibition.getOutputFolder();
                if (oldFolder != null) {
                    exhibition.setOutputFolder(migrate(oldFolder));
                    newDbManager.storeAndCommit(exhibition);
                    exhibition.setOutputFolder(oldFolder);
                } else
                    newDbManager.storeAndCommit(exhibition);
                if (monitor.isCanceled())
                    return abort();
                monitor.worked(incr);
                work -= incr;
            }
            monitor.worked(work);
            if (copyObjects(WebExhibitImpl.class, 50000))
                return abort();
            if (copyObjects(WebParameterImpl.class, 5000))
                return abort();
            if (copyObjects(StoryboardImpl.class, 5000))
                return abort();
            List<WebGalleryImpl> galleries = dbManager.obtainObjects(WebGalleryImpl.class);
            work = 5000;
            na = galleries.size();
            incr = na == 0 ? work : work / na;
            for (WebGalleryImpl exhibition : galleries) {
                String oldFolder = exhibition.getOutputFolder();
                if (oldFolder != null) {
                    exhibition.setOutputFolder(migrate(oldFolder));
                    newDbManager.storeAndCommit(exhibition);
                    exhibition.setOutputFolder(oldFolder);
                } else
                    newDbManager.storeAndCommit(exhibition);
                if (monitor.isCanceled())
                    return abort();
                monitor.worked(incr);
                work -= incr;
            }
            monitor.subTask(Messages.getString("MigrateOperation.migrating_other_entries")); //$NON-NLS-1$
            monitor.worked(work);
            if (copyObjects(PageLayoutImpl.class, 5000))
                return abort();
            List<BookmarkImpl> bookmarks = dbManager.obtainObjects(BookmarkImpl.class);
            work = 20000;
            na = galleries.size();
            incr = na == 0 ? work : work / na;
            for (BookmarkImpl bookmark : bookmarks) {
                String catFile = bookmark.getCatFile();
                if (catFile == null || new File(catFile).equals(dbManager.getFile())) {
                    bookmark.setCatFile(null);
                    newDbManager.storeAndCommit(bookmark);
                }
                if (monitor.isCanceled())
                    return abort();
                monitor.worked(incr);
                work -= incr;
            }
            monitor.worked(work);
            newDbManager.safeTransaction(null, newMeta);
            if (!failedWatchedFolders.isEmpty() || watchedFoldersWithFilters.isEmpty() || oldMeta.getReadonly()) {
                StringBuilder sb = new StringBuilder();
                sb.append(Messages.getString("MigrateOperation.migration_completed")); //$NON-NLS-1$
                if (!failedWatchedFolders.isEmpty()) {
                    sb.append(Messages.getString("MigrateOperation.failed_watched_folders")); //$NON-NLS-1$
                    for (URI uri : failedWatchedFolders)
                        sb.append("\n\t").append(new File(uri).getPath()); //$NON-NLS-1$
                }
                if (!watchedFoldersWithFilters.isEmpty()) {
                    sb.append(Messages.getString("MigrateOperation.watched_folders_with_filters")); //$NON-NLS-1$
                    for (URI uri : watchedFoldersWithFilters)
                        sb.append("\n\t").append(new File(uri).getPath()); //$NON-NLS-1$
                }
                if (oldMeta.getReadonly())
                    sb.append(Messages.getString("MigrateOperation.read_only")); //$NON-NLS-1$
                finalMessage = sb.toString();
                severity = MessageDialog.WARNING;
            } else {
                finalMessage = Messages.getString("MigrateOperation.migration_completed"); //$NON-NLS-1$
                severity = MessageDialog.INFORMATION;
            }
            return close(info);
        } finally {
            newDbManager.close(CatalogListener.NORMAL);
        }
    }

    @SuppressWarnings("unchecked")
    private boolean copyObjects(@SuppressWarnings("rawtypes") Class clazz, int work) {
        @SuppressWarnings("rawtypes")
        List objects = dbManager.obtainObjects(clazz);
        int na = objects.size();
        int incr = na == 0 ? work : work / na;
        for (Object obj : objects) {
            newDbManager.store(obj);
            if (monitor.isCanceled())
                return true;
            monitor.worked(incr);
            work -= incr;
        }
        newDbManager.commit();
        monitor.worked(work);
        return false;
    }

    private void transferSmartCollection(List<Object> toBeStored, SmartCollection coll, SmartCollection newParent) {
        PostProcessor postProcessor = coll.getPostProcessor();
        SmartCollectionImpl newColl = new SmartCollectionImpl(coll.getName(), coll.getSystem(), coll.getAlbum(),
                coll.getAdhoc(), coll.getNetwork(), coll.getDescription(), coll.getColorCode(),
                coll.getLastAccessDate(), coll.getGeneration(), coll.getPerspective(), coll.getShowLabel(),
                coll.getLabelTemplate(), coll.getFontSize(), postProcessor);
        String id = coll.getStringId();
        newColl.setStringId(id);
        toBeStored.add(newColl);
        if (newParent != null) {
            newParent.addSubSelection(newColl);
            newColl.setSmartCollection_subSelection_parent(newParent);
        } else
            newColl.setGroup_rootCollection_parent(coll.getGroup_rootCollection_parent());
        if (postProcessor instanceof IPostProcessor) {
            PostProcessor newProcessor = ((IPostProcessor) postProcessor).clone();
            newProcessor.setStringId(postProcessor.getStringId());
            newProcessor.setSmartCollection_parent(newColl);
            newColl.setPostProcessor(newProcessor);
            toBeStored.add(newProcessor);
        }
        for (Criterion crit : coll.getCriterion()) {
            Object value = crit.getValue();
            Criterion newCrit = new CriterionImpl(crit.getField(), crit.getSubfield(), value, crit.getRelation(),
                    crit.getAnd());
            newCrit.setStringId(crit.getStringId());
            newColl.addCriterion(newCrit);
            newCrit.setSmartCollection_parent(newColl);
            toBeStored.add(newCrit);
            // Utilities.addCustomType(newCrit.getValue(), toBeStored);
            if (!coll.getSystem()) {
                if (QueryField.URI.getKey().equals(crit.getField())) {
                    String uri = (String) value;
                    String path;
                    if (uri.startsWith(IVolumeManager.FILE)) {
                        try {
                            path = new File(new URI(uri)).getPath();
                        } catch (URISyntaxException e) {
                            path = uri.substring(IVolumeManager.FILE.length()).replace('/', File.separatorChar);
                        }
                        String migrated = migrate(path);
                        if (migrated.isEmpty()) {
                            if (coll.getSmartCollection_subSelection_parent() == null) {
                                GroupImpl group = newDbManager.obtainById(GroupImpl.class,
                                        coll.getGroup_rootCollection_parent());
                                group.removeRootCollection(id);
                                newDbManager.storeAndCommit(group);
                            }
                            return;
                        }
                        String migratedUri = toUri(migrated);
                        newCrit.setValue(migratedUri);
                    }
                }
            }
        }
        for (SortCriterion crit : coll.getSortCriterion()) {
            SortCriterion newCrit = new SortCriterionImpl(crit.getField(), crit.getSubfield(),
                    crit.getDescending());
            newCrit.setStringId(crit.getStringId());
            newColl.addSortCriterion(newCrit);
            newCrit.setSmartCollection_parent(newColl);
            toBeStored.add(newCrit);
        }
        for (SmartCollection subColl : coll.getSubSelection())
            transferSmartCollection(toBeStored, subColl, newColl);
        AomList<String> assets = coll.getAsset();
        if (assets != null) {
            List<String> newAssets = new ArrayList<String>(assets.size());
            for (String asset : assets)
                if (newDbManager.obtainById(AssetImpl.class, asset) != null)
                    newAssets.add(asset);
            newColl.setAsset(newAssets);
        }
    }

    private static String toUri(String source) {
        try {
            String sp = source.replace('\\', '/');
            if (!sp.startsWith("/")) //$NON-NLS-1$
                sp = "/" + sp; //$NON-NLS-1$
            if (sp.startsWith("//")) //$NON-NLS-1$
                sp = "//" + sp; //$NON-NLS-1$
            return new URI(Constants.FILESCHEME, null, sp, null).toString();
        } catch (URISyntaxException e) {
            // should not happen
            return source;
        }
    }

    private String extractVolume(String migratedPath) {
        if (migratedPath == null)
            return null;
        if (winTarget) {
            if (currentVolume != null && !currentVolume.isEmpty())
                return currentVolume;
        } else if (migratedPath.startsWith("/")) //$NON-NLS-1$
            return ((VolumeManager) volumeManager).extractLinuxPath(migratedPath);
        return null;
    }

    private String migrateUri(String sourceUri, String volume) {
        if (sourceUri == null || !sourceUri.startsWith(IVolumeManager.FILE))
            return ""; //$NON-NLS-1$
        try {
            String path = new File(new URI(sourceUri)).getPath();
            if (sourceUri.endsWith("/") && !path.endsWith(File.separator)) //$NON-NLS-1$
                path += File.separator;
            if (Constants.WIN32 && volume != null) {
                int i = path.indexOf(':');
                if (i == 1)
                    return migrate(volume + path.substring(1));
            }
            return migrate(path);
        } catch (URISyntaxException e) {
            return ""; //$NON-NLS-1$
        }
    }

    private String migrate(String s) {
        currentVolume = null;
        for (int i = 0; i < rules.length; i++) {
            Pattern pattern = patterns[i];
            MigrationRule rule = rules[i];
            Matcher matcher = pattern.matcher(s);
            if (matcher.matches()) {
                currentVolume = rule.getTargetVolume();
                String targetPattern = rule.getTargetPattern();
                if (targetPattern == null || targetPattern.isEmpty())
                    break;
                StringBuffer sb = new StringBuffer();
                matcher.appendReplacement(sb, targetPattern);
                String result = sb.toString();
                switch (fileSeparatorPolicy) {
                case 1:
                    return result.replace('\\', '/');
                case 2:
                    return result.replace('/', '\\');
                default:
                    return result;
                }
            }
        }
        return ""; //$NON-NLS-1$
    }

    /**
     * @return finalMessage
     */
    public String getFinalMessage() {
        return finalMessage;
    }

    /**
     * @return severity
     */
    public int getSeverity() {
        return severity;
    }

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

}