/* *------------------------------------------------------------------------------ * Copyright (C) 2015 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 ij.IJ; import ij.ImagePlus; import ij.io.FileInfo; import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.io.StringReader; import java.io.StringWriter; import java.net.URL; import java.util.ArrayList; import java.util.List; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import loci.formats.codec.CompressionType; import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; import org.openmicroscopy.shoola.util.CommonsLangUtils; import org.w3c.dom.Document; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.InputSource; import org.xml.sax.SAXException; /** * Object hosting the information about the "file" to import. * * @author Jean-Marie Burel      * <a href="mailto:j.burel@dundee.ac.uk">j.burel@dundee.ac.uk</a> * @since 5.0 */ public class FileObject { /** The field identifying the image id.*/ public static final String OMERO_ID = "Omero_iid"; /** The field identifying the group id.*/ public static final String OMERO_GROUP = "Omero_group"; /** The file to import. * This could be a file on disk or an ImageJ object for example. */ private Object file; /** * Flag indicating if the file is generated or not. */ private boolean generated; /** * List of associated files. Mainly for imageJ. */ private List<FileObject> associatedFiles; /** The trueFile if available.*/ private File trueFile; /** * Returns the Pixels node matching the index. * * @param doc The document to handle. * @return See above. */ private Node getPixelsNode(Document doc) { NodeList l = doc.getElementsByTagName("Image"); if (l == null || l.getLength() == 0) return null; NamedNodeMap attributes; String value; Node node; NodeList nodeList; int series = getIndex(); for (int i = 0; i < l.getLength(); i++) { node = l.item(i); if (node.hasAttributes()) { attributes = node.getAttributes(); value = attributes.getNamedItem("ID").getNodeValue(); if (value.equals("Image:"+series)) { nodeList = node.getChildNodes(); if (nodeList != null && nodeList.getLength() > 0) { for (int j = 0; j < nodeList.getLength(); j++) { Node n = nodeList.item(j); if ("Pixels".equals(n.getNodeName())) { return n; } } } } } } return null; } /** * Parses the image's description. * * @param xmlStr The string to parse. * @return See above. */ private Document xmlParser(String xmlStr) throws SAXException { InputSource stream = new InputSource(); stream.setCharacterStream(new StringReader(xmlStr)); StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); DocumentBuilder builder; Document doc = null; try { builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); doc = builder.parse(stream); } catch (ParserConfigurationException e) { e.printStackTrace(pw); IJ.log(sw.toString()); } catch (IOException e) { e.printStackTrace(pw); IJ.log(sw.toString()); } finally { try { sw.close(); } catch (IOException e) { IJ.log("I/O Exception:" + e.getMessage()); } pw.close(); } return doc; } /** * Creates a new instance. * * @param file The file to import. */ public FileObject(Object file) { if (file == null) throw new IllegalArgumentException("No object to import"); this.file = file; } /** * Sets the omero image Id after saving the image. * * @param id The value to set. */ public void setImageID(long id) { if (!isImagePlus()) return; ImagePlus image = (ImagePlus) file; image.setProperty(OMERO_ID, id); } /** * Add the associated file if any. * * @param file The file to add. */ public void addAssociatedFile(FileObject file) { if (associatedFiles == null) { associatedFiles = new ArrayList<FileObject>(); } if (file != null) { associatedFiles.add(file); } } /** * Returns the associated files if any or <code>null</code>. * * @return See above. */ public List<FileObject> getAssociatedFiles() { return associatedFiles; } /** * Returns the object to import. * * @return See above */ public Object getFile() { return file; } /** * Returns the name of the object to import. * * @return See above. */ public String getName() { if (file instanceof File) { return ((File) file).getName(); } else if (file instanceof ImagePlus) { ImagePlus img = (ImagePlus) file; return img.getTitle(); } return null; } /** * Returns the absolute path to the file. * * @return See above. */ public String getAbsolutePath() { if (file instanceof File) { return ((File) file).getAbsolutePath(); } else if (file instanceof ImagePlus) { File f = getTrueFile(); if (f != null) return f.getAbsolutePath(); return ((ImagePlus) file).getTitle(); } return ""; } /** * Returns the file to import. * @return See above. */ public File getFileToImport() { File f = getTrueFile(); if (f != null) return f; if (file instanceof ImagePlus) { //prepare command ImagePlus img = (ImagePlus) file; generated = true; try { //name w/o extension String baseName = FilenameUtils.getBaseName( FilenameUtils.removeExtension(img.getTitle())); baseName = CommonsLangUtils.deleteWhitespace(baseName); String n = baseName+".ome.tif"; f = File.createTempFile(img.getTitle(), ".ome.tif"); File p = f.getParentFile(); File[] list = p.listFiles(); if (list != null) { File toDelete = null; for (int i = 0; i < list.length; i++) { if (list[i].getName().equals(n)) { toDelete = list[i]; break; } } if (toDelete != null) { toDelete.delete(); } } f = new File(p, n); f.deleteOnExit(); } catch (Exception e) { return null; } StringBuffer buffer = new StringBuffer(); buffer.append("outfile="+f.getAbsolutePath()); buffer.append(" splitz=false"); buffer.append(" splitc=false"); buffer.append(" splitt=false"); buffer.append(" saveroi=false"); buffer.append(" compression="+CompressionType.UNCOMPRESSED.getCompression()); buffer.append(" imageid="+img.getID()+" "); IJ.runPlugIn("loci.plugins.LociExporter", buffer.toString()); return f; } return null; } /** * Returns <code>true</code> if the file has been generated, * <code>false</code> otherwise. * * @return See above. */ public boolean isGenerated() { return generated; } /** * Returns <code>true</code> if it is a new image from ImageJ, * <code>false</code> otherwise. * * @return See above. */ public boolean isNewImage() { if (file instanceof ImagePlus) { ImagePlus img = (ImagePlus) file; if (img.changes) return true; FileInfo info = img.getOriginalFileInfo(); if (info == null) { info = img.getFileInfo(); String name = info.fileName; if (CommonsLangUtils.isBlank(name) || "Untitled".equals(name)) return true; } String xmlStr = info.description; if (CommonsLangUtils.isBlank(xmlStr)) return false; //Get Current Dimensions int sizeC_cur = img.getNChannels(); int sizeT_cur = img.getNFrames(); int sizeZ_cur = img.getNSlices(); int sizeC_org = sizeC_cur; int sizeT_org = sizeT_cur; int sizeZ_org = sizeZ_cur; Document doc = null; boolean xml = false; try { if (xmlStr.startsWith("<")) { doc = xmlParser(xmlStr); } } catch (SAXException e) { //not XML or not possible to read it correctly xml = false; } if (!xml) { //try to parse the string String[] values = xmlStr.split("\n"); String v; for (int i = 0; i < values.length; i++) { v = values[i]; if (v.startsWith("slices")) { String[] keys = v.split("="); if (keys.length > 1) { sizeZ_org = Integer.valueOf(keys[1]); } } else if (v.startsWith("channels")) { String[] keys = v.split("="); if (keys.length > 1) { sizeC_org = Integer.valueOf(keys[1]); } } else if (v.startsWith("frames")) { String[] keys = v.split("="); if (keys.length > 1) { sizeT_org = Integer.valueOf(keys[1]); } } } } if (doc != null) { Node node = getPixelsNode(doc); if (node == null) return false; NamedNodeMap nnm = node.getAttributes(); sizeC_org = Integer.valueOf(nnm.getNamedItem("SizeC").getNodeValue()); sizeT_org = Integer.valueOf(nnm.getNamedItem("SizeT").getNodeValue()); sizeZ_org = Integer.valueOf(nnm.getNamedItem("SizeZ").getNodeValue()); } if (sizeC_cur != sizeC_org || sizeT_cur != sizeT_org || sizeZ_cur != sizeZ_org) { return true; } } return false; } /** * Returns the file to import. * * @return See above. */ public File getTrueFile() { if (file instanceof File) { return (File) file; } else if (file instanceof ImagePlus) { if (trueFile != null) return trueFile; ImagePlus img = (ImagePlus) file; if (!img.changes) { FileInfo info = img.getOriginalFileInfo(); if (info != null) { if (CommonsLangUtils.isNotEmpty(info.url)) { //create a tmp file and copy the URL String fname = img.getTitle(); String extension = FilenameUtils.getExtension(fname); String baseName = FilenameUtils.getBaseName( FilenameUtils.removeExtension(fname)); try { trueFile = File.createTempFile(baseName, "."+extension); trueFile.deleteOnExit(); FileUtils.copyURLToFile(new URL(info.url), trueFile); } catch (Exception e) { //ignore. } return trueFile; } if (info.directory != null && info.fileName != null) { trueFile = new File(info.directory, info.fileName); return trueFile; } } } } return null; } /** * Returns the name of the parent file if it exists. * * @return See above. */ public String getParentName() { File f = getTrueFile(); if (f == null || f.getParentFile() == null) return null; return f.getParentFile().getName(); } /** * Returns the size of the file * * @return See above. */ public long getLength() { File f; if (file instanceof File) { f = (File) file; if (f.isFile()) return f.length(); return FileUtils.sizeOfDirectory(f); } else if (file instanceof ImagePlus) { f = getTrueFile(); if (f != null) return f.length(); } return 0; } /** * Returns <code>true</code> if it is a directory, <code>false</code> * otherwise. * * @return See above. */ public boolean isDirectory() { if (file instanceof File) { File f = (File) file; return f.isDirectory(); } return false; } /** * Returns <code>true</code> if it is a file, <code>false</code> * otherwise. * * @return See above. */ public boolean isFile() { if (file instanceof File) { File f = (File) file; return f.isFile(); } return true; } /** * Returns <code>true</code> if it is an image from ImageJ, * <code>false</code> otherwise. * * @return See above. */ public boolean isImagePlus() { return file instanceof ImagePlus; } /** * Returns the index of the image if it is an image plus. * * @return See above. */ public int getIndex() { if (!isImagePlus()) return -1; ImagePlus image = (ImagePlus) file; Object value = image.getProperty("Series"); if (value != null && value instanceof Integer) return ((Integer) value).intValue(); return -1; } /** * Returns the <code>OMERO</code> id or <code>-1</code> if not set. * * @return See above. */ public long getOMEROID() { if (!isImagePlus()) return -1; ImagePlus image = (ImagePlus) file; Object value = image.getProperty(OMERO_ID); if (value != null && value instanceof Long) return ((Long) value).longValue(); return -1; } /** * Returns the <code>OMERO</code> group id or <code>-1</code> if not set. * * @return See above. */ public long getGroupID() { if (!isImagePlus()) return -1; ImagePlus image = (ImagePlus) file; Object value = image.getProperty(OMERO_GROUP); if (value != null && value instanceof Long) return ((Long) value).longValue(); return -1; } /** * Returns the name as container if option is on. * * @return See above. */ public String getFolderAsContainerName() { File parentFile; if (file instanceof File) { File f = (File) file; if (f.isFile()) { parentFile = f.getParentFile(); if (parentFile == null) return null; return parentFile.getName(); } return f.getName(); } else { File f = getTrueFile();//image plus if (f != null && f.getParentFile() != null) return f.getParentFile().getName(); return getName(); } } }