/* *------------------------------------------------------------------------------ * Copyright (C) 2006-2010 University of Dundee. All rights reserved. * * * This program 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. * This program 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 this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * *------------------------------------------------------------------------------ */ package org.openmicroscopy.shoola.env.data.model; import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import loci.formats.FormatTools; import loci.formats.IFormatReader; import loci.formats.ImageReader; import loci.formats.in.OMEXMLReader; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.io.FilenameUtils; import omero.gateway.SecurityContext; import org.openmicroscopy.shoola.util.CommonsLangUtils; import org.openmicroscopy.shoola.util.filter.file.TIFFFilter; import org.openmicroscopy.shoola.util.ui.UIUtilities; import omero.gateway.model.DataObject; import omero.gateway.model.DatasetData; import omero.gateway.model.ProjectData; import omero.gateway.model.ScreenData; import omero.gateway.model.TagAnnotationData; /** * Helper class where parameters required for the imports are stored. * * @author Jean-Marie Burel      * <a href="mailto:j.burel@dundee.ac.uk">j.burel@dundee.ac.uk</a> * @author Donald MacDonald      * <a href="mailto:donald@lifesci.dundee.ac.uk">donald@lifesci.dundee.ac.uk</a> * @version 3.0 * @since 3.0-Beta4 */ public class ImportableObject { /** The default name for the dataset. */ public static final String DEFAULT_DATASET_NAME; /** * The collection of HCS files extensions to check before importing. */ public static final Set<String> HCS_FILES_EXTENSION; /** * The collection of arbitrary files extensions to check * before importing. If a file has one of the extensions, we need * to check the import candidates. */ private static final List<String> ARBITRARY_FILES_EXTENSION; /** * The collection of HCS format. */ public static final List<String> HCS_DOMAIN; /** * The collection of OME suffices. */ public static final List<String> OME_SUFFIXES; /** The filter used to exclude extensions.*/ public static final TIFFFilter FILTER; /** The <code>dat</code> extension.*/ public static final String DAT_EXTENSION = "dat"; static { FILTER = new TIFFFilter(); DEFAULT_DATASET_NAME = UIUtilities.formatDate(null, UIUtilities.D_M_Y_FORMAT); HCS_FILES_EXTENSION = new HashSet<String>(); HCS_DOMAIN = new ArrayList<String>(); ImageReader r = new ImageReader(); IFormatReader[] allReaders = r.getReaders(); try { for (IFormatReader reader : allReaders) { if (Arrays.asList(reader.getPossibleDomains("")).contains( FormatTools.HCS_DOMAIN)) { populateExtensions(reader.getSuffixes()); HCS_DOMAIN.add(reader.getFormat()); } reader.close(); } } catch (Exception e) {} finally { try { r.close(); } catch (Exception ex) {} } IFormatReader reader = new OMEXMLReader(); OME_SUFFIXES = (List<String>) Arrays.asList(reader.getSuffixes()); ARBITRARY_FILES_EXTENSION = new ArrayList<String>(); ARBITRARY_FILES_EXTENSION.add("text"); ARBITRARY_FILES_EXTENSION.add("txt"); ARBITRARY_FILES_EXTENSION.add("xml"); ARBITRARY_FILES_EXTENSION.add("exp"); ARBITRARY_FILES_EXTENSION.add("log"); ARBITRARY_FILES_EXTENSION.add("ini"); ARBITRARY_FILES_EXTENSION.add("dat"); ARBITRARY_FILES_EXTENSION.add(TIFFFilter.TIFF); ARBITRARY_FILES_EXTENSION.add(TIFFFilter.TIF); } /** * Adds the specified suffixes to the list. * * @param suffixes The values to handle. */ private static void populateExtensions(String[] suffixes) { if (suffixes != null) { String s; for (int i = 0; i < suffixes.length; i++) { s = suffixes[i]; if (s != null && s.trim().length() > 0) HCS_FILES_EXTENSION.add(s.toLowerCase()); } } } /** * Returns <code>true</code> if the extension of the specified file * is arbitrary and so requires to use the import candidates, * <code>false</code> otherwise. * * @param f The file to handle. * @return See above. */ public static boolean isArbitraryFile(File f) { if (f == null) return false; String name = f.getName(); if (!name.contains(".")) return false; String ext = FilenameUtils.getExtension(name); return ARBITRARY_FILES_EXTENSION.contains(ext); } /** The collection of files to import. */ private List<ImportableFile> files; /** The depth when the name is overridden. */ private int depthForName; /** The depth used when scanning a folder. */ private int scanningDepth; /** * Flag indicating to override the name set by B-F when importing the data. */ private boolean overrideName; /** The collection of tags. */ private Collection<TagAnnotationData> tags; /** The array containing pixels size.*/ private double[] pixelsSize; /** The type to create if the folder has to be saved as a container. */ private Class type; /** Flag indicating to load the thumbnails. */ private boolean loadThumbnail; /** The nodes of reference. */ private List<Object> refNodes; /** The collection of new objects. */ private List<DataObject> newObjects; /** The collection of new object. */ private Map<Long, List<DatasetData>> projectDatasetMap; /** * Returns the object corresponding to the passed file. * * @param f The file to handle. * @return See above. */ private ImportableFile getImportableFile(File f) { Iterator<ImportableFile> i = files.iterator(); String path = f.getAbsolutePath(); ImportableFile iFile; while (i.hasNext()) { iFile = i.next(); if (path.equals(iFile.getFile().getAbsolutePath())) return iFile; } return null; } /** * Returns the name of the object. * * @param object The object to handle. * @return See above. */ private String getObjectName(DataObject object) { if (object instanceof DatasetData) { return ((DatasetData) object).getName(); } if (object instanceof ProjectData) { return ((ProjectData) object).getName(); } if (object instanceof ScreenData) { return ((ScreenData) object).getName(); } return ""; } /** * Creates a new instance. * * @param files The collection of files to import. * @param overrideName Pass <code>true</code> to override the name of the * file set while importing the data, * <code>false</code> otherwise. */ public ImportableObject(List<ImportableFile> files, boolean overrideName) { this.files = files; this.overrideName = overrideName; type = DatasetData.class; depthForName = -1; loadThumbnail = true; newObjects = new ArrayList<DataObject>(); projectDatasetMap = new HashMap<Long, List<DatasetData>>(); } /** * Sets to <code>true</code> if the thumbnail has to be loaded when * the image is imported, <code>false</code> otherwise. * * @param loadThumbnail Pass <code>true</code> to load the thumbnail when * the image is imported, <code>false</code> otherwise. */ public void setLoadThumbnail(boolean loadThumbnail) { this.loadThumbnail = loadThumbnail; } /** * Returns <code>true</code> if the thumbnail has to be loaded when * the image is imported, <code>false</code> otherwise. * * @return See above. */ public boolean isLoadThumbnail() { return loadThumbnail; } /** * Sets the type to use when creating a folder as container. * * @param type The type to use. */ public void setType(Class type) { this.type = type; } /** * Sets the default size of the pixels if the value is not found. * * @param pixelsSize The value to set. */ public void setPixelsSize(double[] pixelsSize) { this.pixelsSize = pixelsSize; } /** * Sets the collection of tags. * * @param tags The tags to use. */ public void setTags(Collection<TagAnnotationData> tags) { this.tags = tags; } /** * Sets the depth used scanning a folder. * * @param scanningDepth The value to set. */ public void setScanningDepth(int scanningDepth) { this.scanningDepth = scanningDepth; } /** * Returns the depth used scanning a folder. * * @return See above. */ public int getScanningDepth() { return scanningDepth; } /** * Sets the depth used when the name is overridden. * * @param depthForName The value to set. */ public void setDepthForName(int depthForName) { this.depthForName = depthForName; } /** * Returns the depth used when the name is overridden. * * @return See above. */ public int getDepthForName() { return depthForName; } /** * Returns the collection of files to import. * * @return See above. */ public List<ImportableFile> getFiles() { return files; } /** * Returns the <code>DataObject</code> corresponding to the folder * be saved as a container. * * @param file The file to handle. * @return See above. */ public DataObject createFolderAsContainer(ImportableFile file) { return createFolderAsContainer(file, false); } /** * Returns the <code>DataObject</code> corresponding to the folder * be saved as a container. * * @param file The file to handle. * @param hcs Pass <code>true</code> to indicate that the folder * to create is for HCS data, <code>false</code> otherwise. * @return See above. */ public DataObject createFolderAsContainer(ImportableFile file, boolean hcs) { if (file == null) return null; Class<?> klass = type; if (hcs) klass = ScreenData.class; FileObject f = file.getFile(); boolean b = file.isFolderAsContainer(); if (!b) return null; String name = f.getFolderAsContainerName(); if (CommonsLangUtils.isBlank(name)) return null; if (DatasetData.class.equals(klass)) { DatasetData dataset = new DatasetData(); dataset.setName(name); return dataset; } else if (ScreenData.class.equals(klass)) { ScreenData screen = new ScreenData(); screen.setName(name); return screen; } return null; } /** * Returns the root type used when creating the object. * * @return See above. */ public Class getRootType() { if (ScreenData.class.equals(type)) return type; return ProjectData.class; } /** * Returns <code>true</code> if the name set while importing the data * has to be overridden, <code>false</code> otherwise. * * @return See above. */ public boolean isOverrideName() { return overrideName; } /** * Returns the pixels size to use of the value is not found in the * file. * * @return See above. */ public Double[] getPixelsSize() { if (pixelsSize != null && pixelsSize.length > 0) { Double[] array = new Double[pixelsSize.length]; for (int i = 0; i < pixelsSize.length; i++) array[i] = new Double(pixelsSize[i]); return array; } return null; } /** * Returns the collection of tags. * * @return See above. */ public Collection<TagAnnotationData> getTags() { return tags; } /** * Returns <code>true</code> if new tags were created, <code>false</code> * otherwise. * * @return See above. */ public boolean hasNewTags() { if (tags == null || tags.size() == 0) return false; Iterator<TagAnnotationData> i = tags.iterator(); TagAnnotationData tag; while (i.hasNext()) { tag = i.next(); if (tag.getId() <= 0) return true; } return false; } /** * Returns the nodes of reference. * * @return See above. */ public List<Object> getRefNodes() { return refNodes; } /** * Returns the nodes of reference. * * @param refNodes The value to set. */ public void setRefNodes(List<Object> refNodes) { this.refNodes = refNodes; } /** * Returns <code>true</code> if the extension of the specified file * is a HCS files, <code>false</code> otherwise. * * @param f The file to handle. * @return See above. */ public static boolean isHCSFile(FileObject f) { if (f == null) return false; String path = f.getAbsolutePath(); if (FILTER.accept(path)) return false; String name = path; if (!name.contains(".")) return false; String ext = name.substring(name.lastIndexOf('.')+1, name.length()); if (ext == null) return false; return HCS_FILES_EXTENSION.contains(ext.toLowerCase()); } /** * Returns <code>true</code> if the passed format is a HCS format, * <code>false</code> otherwise. * * @param format The format to handle. * @return See above. */ public static boolean isHCSFormat(String format) { Iterator<String> i = HCS_DOMAIN.iterator(); while (i.hasNext()) { if (format.contains(i.next())) return true; } return false; } /** * Returns code <code>true</code> if the specified file is an * <code>OME</code> file, <code>false</code> otherwise. * * @param file The file to handle. * @return See above. */ public static boolean isOMEFile(File file) { if (file == null) return false; String name = file.getName(); if (name == null) return false; Iterator<String> i = OME_SUFFIXES.iterator(); name = name.toLowerCase(); String s; while (i.hasNext()) { s = i.next().toLowerCase(); if (name.endsWith(s)) return true; } return false; } /** * Returns <code>true</code> if new objects have to be created, * <code>false</code> otherwise. * * @return See above. */ public boolean hasNewObjects() { int size = newObjects.size(); if (size > 0) return true; return projectDatasetMap.size() > 0; } /** * Adds a new object. * * @param object The object to add. */ public void addNewDataObject(DataObject object) { if (object != null) newObjects.add(object); } /** * Returns the object if it has already been created in the specified * context, <code>null</code> otherwise. * * @param object The object to check. * @return See above. */ public DataObject hasObjectBeenCreated(DataObject object, SecurityContext ctx) { if (object == null) return null; Iterator<DataObject> i = newObjects.iterator(); DataObject data; String name = getObjectName(object); String n; while (i.hasNext()) { data = i.next(); n = getObjectName(data); if (data.getClass().equals(object.getClass()) && n.equals(name)) { if (data.getGroupId() == ctx.getGroupID()) return data; } } return null; } /** * Returns the dataset if already created. * * @param projectID The id of the project. * @param dataset The dataset to register. * @return See above.s */ public DatasetData isDatasetCreated(long projectID, DatasetData dataset) { List<DatasetData> datasets = projectDatasetMap.get(projectID); if (datasets == null || datasets.size() == 0) return null; Iterator<DatasetData> i = datasets.iterator(); DatasetData data; String name = dataset.getName(); while (i.hasNext()) { data = i.next(); if (data.getName().equals(name)) return data; } return null; } /** * Registers the dataset. * * @param projectID The id of the project. * @param dataset The dataset to register. */ public void registerDataset(long projectID, DatasetData dataset) { if (dataset == null) return; List<DatasetData> datasets = projectDatasetMap.get(projectID); if (datasets == null) { datasets = new ArrayList<DatasetData>(); projectDatasetMap.put(projectID, datasets); } datasets.add(dataset); } /** * Returns <code>true</code> if the file is already in the list of files * to import e.g. the file and the companion file are selected, * <code></code> otherwise. * @param value The path to the file. * @return See above. */ public boolean isFileinQueue(String value) { Iterator<ImportableFile> i = files.iterator(); ImportableFile f; while (i.hasNext()) { f = i.next(); if (f.getFile().getAbsolutePath().equals(value)) return true; } return false; } /** * Resets the files to re-upload * * @param files The files to reupload. */ public void reUpload(List<ImportableFile> files) { if (CollectionUtils.isEmpty(files)) return; this.files = files; } }