ijfx.explorer.core.DefaultFolderManagerService.java Source code

Java tutorial

Introduction

Here is the source code for ijfx.explorer.core.DefaultFolderManagerService.java

Source

/*
This file is part of ImageJ FX.
    
ImageJ FX 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 3 of the License, or
(at your option) any later version.
    
ImageJ FX 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 ImageJ FX.  If not, see <http://www.gnu.org/licenses/>. 
    
 Copyright 2015,2016 Cyril MONGIS, Michael Knop
       
 */
package ijfx.explorer.core;

import ijfx.core.activity.ActivityService;
import ijfx.core.io.ExplorableIOService;
import ijfx.core.metadata.MetaData;
import ijfx.core.metadata.MetaDataService;
import ijfx.core.metadata.MetaDataSetType;
import ijfx.core.notification.DefaultNotification;
import ijfx.core.notification.NotificationService;
import ijfx.core.prefs.JsonPreferenceService;
import ijfx.core.stats.ImageStatisticsService;
import ijfx.core.uicontext.UiContextService;
import ijfx.explorer.ExplorationMode;
import ijfx.explorer.ExplorerActivity;
import ijfx.explorer.datamodel.Explorable;
import ijfx.explorer.datamodel.wrappers.PlaneMetaDataSetWrapper;
import ijfx.explorer.events.ExplorationModeChangeEvent;
import ijfx.explorer.events.FolderAddedEvent;
import ijfx.explorer.events.FolderDeletedEvent;
import ijfx.explorer.events.FolderUpdatedEvent;
import ijfx.ui.main.ImageJFX;
import ijfx.ui.loading.LoadingScreenService;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import mongis.utils.task.FluentTask;
import mongis.utils.task.ProgressHandler;
import mongis.utils.task.SilentProgressHandler;
import net.imagej.Dataset;
import net.imagej.display.ImageDisplay;
import net.imagej.display.ImageDisplayService;
import org.apache.commons.math3.stat.descriptive.SummaryStatistics;
import org.scijava.Context;
import org.scijava.event.EventHandler;
import org.scijava.event.EventService;
import org.scijava.plugin.Parameter;
import org.scijava.plugin.Plugin;
import org.scijava.service.AbstractService;
import org.scijava.service.Service;
import ijfx.explorer.ExplorerViewService;

/**
 *
 * @author Cyril MONGIS, 2016
 */
@Plugin(type = Service.class)
public class DefaultFolderManagerService extends AbstractService implements FolderManagerService {

    List<Folder> folderList;

    Folder currentFolder;

    @Parameter
    ExplorerViewService explorerService;

    @Parameter
    EventService eventService;

    @Parameter
    Context context;

    @Parameter
    UiContextService uiContextService;

    @Parameter
    JsonPreferenceService jsonPrefService;

    @Parameter
    MetaDataService metaDataExtractionService;

    @Parameter
    LoadingScreenService loadingScreenService;

    @Parameter
    ImageStatisticsService statsService;

    @Parameter
    NotificationService notificationService;

    @Parameter
    ImageDisplayService imageDisplayService;

    @Parameter
    ActivityService activityService;

    Logger logger = ImageJFX.getLogger();

    ExplorationMode currentExplorationMode = ExplorationMode.FILE;

    List<Explorable> currentItems;

    ExecutorService executorService = Executors.newFixedThreadPool(1);

    private Folder recentFileFolder;

    @Override
    public Folder addFolder(File file) {
        Folder folder = null;
        if (file.isDirectory()) {
            folder = new DefaultFolder(context, file);
        } else if (file.getName().endsWith(ExplorableIOService.DB_EXTENSION)) {
            folder = new DatabaseFolder(context, file);
        } else {
            throw new IllegalArgumentException("File should be a directory or Database file.");
        }
        return addFolder(folder);
    }

    protected Folder addFolder(Folder f) {
        getFolderList().add(f);

        if (folderList.size() == 1) {
            setCurrentFolder(f);
        }

        eventService.publishLater(new FolderAddedEvent().setObject(f));
        save();
        return f;
    }

    @Override
    public List<Folder> getFolderList() {

        if (folderList == null) {
            folderList = new ArrayList<>();
            load();
        }

        return folderList;
    }

    @Override
    public Folder getCurrentFolder() {
        return currentFolder;
    }

    @Override
    public void setCurrentFolder(Folder folder) {
        currentFolder = folder;

        if (currentFolder == null) {

            setItems(new ArrayList<>());
            updateExploredElements();
        } else {

            logger.info("Setting current folder " + folder.getName());

            uiContextService.enter("explore-files");
            uiContextService.update();
            updateExploredElements();
        }
    }

    @EventHandler
    public void onFolderUpdated(FolderUpdatedEvent event) {
        logger.info("Folder updated ! " + event.getObject().getName());
        if (currentFolder == event.getObject()) {
            updateExploredElements();
        }
    }

    @Override
    public void setExplorationMode(ExplorationMode mode) {
        if (mode == currentExplorationMode) {
            return;
        }
        currentExplorationMode = mode;
        eventService.publishLater(new ExplorationModeChangeEvent().setObject(mode));
        updateExploredElements();
    }

    private void updateExploredElements() {

        ExplorationMode mode = currentExplorationMode;
        logger.info("Updating current elements");
        FluentTask<Void, List<Explorable>> task = new FluentTask<>();
        task.setName("Fetching elements...");

        if (currentFolder == null) {
            return;
        } else {

            if (mode != null) {
                switch (mode) {
                case FILE:
                    task.call(currentFolder::getFileList);
                    break;
                case PLANE:
                    task.call(currentFolder::getPlaneList);
                    break;
                case OBJECT:
                    task.call(currentFolder::getObjectList);

                }
            }
            task.then(this::setItems);
            task.startIn(executorService);
            loadingScreenService.frontEndTask(task, false);
        }
        if (mode != null) {
            logger.info("Exploration mode changed : " + mode.toString());
        }
    }

    private void setItems(List<Explorable> items) {

        if (items != null) {
            logger.info(String.format("Setting %d items", items.size()));
        } else {
            logger.info("Items are null");
        }
        explorerService.setItems(items);
        explorerService.update();
    }

    private Integer fetchMoreStatistics(ProgressHandler progress, List<Explorable> explorableList) {
        if (progress == null) {
            progress = new SilentProgressHandler();
        }
        progress.setStatus("Completing statistics of the objects");
        Integer elementAnalyzedCount = 0;
        int elements = explorableList.size();
        int i = 0;
        for (Explorable e : explorableList) {
            if (!e.getMetaDataSet().containsKey(MetaData.STATS_PIXEL_MIN)) {
                progress.setProgress(i, elements);
                MetaDataSetType type = e.getMetaDataSet().getType();
                if (type == MetaDataSetType.FILE || type == MetaDataSetType.PLANE) {

                    SummaryStatistics stats = statsService.getSummaryStatistics(e.getDataset());

                    e.getMetaDataSet().merge(statsService.summaryStatisticsToMap(stats));
                    elementAnalyzedCount++;
                }
            }
            i++;
        }
        return elementAnalyzedCount;
    }

    @Override
    public ExplorationMode getCurrentExplorationMode() {
        return currentExplorationMode;
    }

    private void save() {
        HashMap<String, String> folderMap = new HashMap<>();
        for (Folder f : getFolderList()) {
            folderMap.put(f.getName(), f.getDirectory().getAbsolutePath());
        }
        jsonPrefService.savePreference(folderMap, FOLDER_PREFERENCE_FILE);
    }

    private synchronized void load() {

        Map<String, String> folderMap = jsonPrefService.loadMapFromJson(FOLDER_PREFERENCE_FILE, String.class,
                String.class);
        folderMap.forEach((name, folderPath) -> {
            File file = new File(folderPath);
            if (file.exists() == false) {
                return;
            }
            Folder folder;
            if (file.isDirectory()) {
                folder = new DefaultFolder(context, file);
                folderList.add(folder);

            } else if (file.getName().endsWith(ExplorableIOService.DB_EXTENSION)) {
                folder = new DatabaseFolder(context, file);
                folderList.add(folder);
            } else {
                return;
            }

        });
    }

    @Override
    public void completeStatistics() {
        loadingScreenService.frontEndTask(new FluentTask<List<Explorable>, Integer>()
                .callback(this::fetchMoreStatistics).setInput(getCurrentFolder().getFileList(ProgressHandler.NONE))
                .then(this::onStatisticComputingEnded).start());

    }

    private void onStatisticComputingEnded(Integer computedImages) {
        notificationService.publish(new DefaultNotification("Statistic Computation",
                String.format("%d images where computed.", computedImages)));
        eventService.publishLater(new FolderUpdatedEvent().setObject(getCurrentFolder()));
    }

    public void removeFolder(Folder folder) {
        folderList.remove(folder);
        eventService.publishLater(new FolderDeletedEvent().setObject(folder));
    }

    @Override
    public Folder getFolderContainingFile(File f) {
        return getFolderList().stream().filter(folder -> folder != null && folder.isFilePartOf(f)).findFirst()
                .orElse(null);
    }

    public void openImageFolder(String imagePath) {
        File sourceFile = new File(imagePath);

        if (sourceFile.exists()) {

            Folder folderContainingFile = getFolderContainingFile(new File(imagePath));

            if (folderContainingFile == null) {
                folderContainingFile = addFolder(new File(imagePath).getParentFile());
            }

            setCurrentFolder(folderContainingFile);
            setExplorationMode(ExplorationMode.FILE);
        }
        activityService.open(ExplorerActivity.class);
    }

    public void openImageFolder(ImageDisplay display) {

        Dataset activeDataset = imageDisplayService.getActiveDataset(display);

        if (activeDataset != null) {

            String source = activeDataset.getSource();
            if (source == null) {
                source = (String) activeDataset.getProperties().get(MetaData.ABSOLUTE_PATH);
            }

            openImageFolder(source);

        }

    }

    @Override
    public List<Explorable> extractPlanes(List<? extends Explorable> list) {

        return list.stream().flatMap(exp -> {

            return metaDataExtractionService.extractPlaneMetaData(exp.getMetaDataSet()).stream()
                    .map(m -> new PlaneMetaDataSetWrapper(getContext(), m));

        }).collect(Collectors.toList());
    }

    @Override
    public Stream<Explorable> extractPlanes(Explorable exp) {
        return metaDataExtractionService.extractPlaneMetaData(exp.getMetaDataSet()).stream()
                .map(m -> new PlaneMetaDataSetWrapper(getContext(), m));

    }

}