/*
*------------------------------------------------------------------------------
* Copyright (C) 2013-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.util.file.modulo;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.apache.commons.collections.CollectionUtils;
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;
/**
* Parses the modulo annotation.
*
* @author Jean-Marie Burel
* <a href="mailto:j.burel@dundee.ac.uk">j.burel@dundee.ac.uk</a>
* @since 5.0
*/
public class ModuloParser
{
/** The tags that we handle. */
private static String[] tagsModulo = {ModuloInfo.MODULO_C,
ModuloInfo.MODULO_Z, ModuloInfo.MODULO_T};
/** The file to parse.*/
private String file;
/** Hosts the contents of the modulo tags.*/
private List<ModuloInfo> modulos;
/** Collects all tags that we have to handle from the file. */
private List<Node> moduloTags;
/** The configuration file. */
private Document document;
/**
* Retrieves the content of the tags that we handle.
* Stores their DOM representation (DOM node) into a list.
*/
private void readModuloEntries()
{
NodeList list;
Node n;
for (int k = 0; k < tagsModulo.length; ++k) {
list = document.getElementsByTagName(tagsModulo[k]);
for (int i = 0; i < list.getLength(); ++i) {
n = list.item(i);
if (n.hasAttributes()) moduloTags.add(n);
}
}
}
/**
* Creates a concrete <code>ModuloInfo</code> object to handle the
* conversion of the content of the passed tag into an object.
*
* @param tag DOM node representing either a <i>modulo</i> tag.
* @return See above.
* @throws Exception If the tag couldn't be handled.
*/
ModuloInfo createModuloFor(Node tag)
throws Exception
{
if (!tag.hasAttributes())
throw new Exception("Missing tag's attributes.");
ModuloInfo info = new ModuloInfo(tag.getNodeName());
NamedNodeMap attributes = tag.getAttributes();
Node attribute;
for (int i = 0; i < attributes.getLength(); ++i) {
attribute = attributes.item(i);
if (ModuloInfo.START.equals(attribute.getNodeName()))
info.setStart(Double.parseDouble(attribute.getNodeValue()));
else if (ModuloInfo.END.equals(attribute.getNodeName()))
info.setEnd(Double.parseDouble(attribute.getNodeValue()));
else if (ModuloInfo.STEP.equals(attribute.getNodeName()))
info.setStep(Double.parseDouble(attribute.getNodeValue()));
else if (ModuloInfo.TYPE.equals(attribute.getNodeName()))
info.setType(attribute.getNodeValue());
else if (ModuloInfo.TYPE_DESCRIPTION.equals(
attribute.getNodeName()))
info.setTypeDescription(attribute.getNodeValue());
else if (ModuloInfo.UNIT.equals(attribute.getNodeName()))
info.setUnit(attribute.getNodeValue());
}
NodeList nodes = tag.getChildNodes();
Double min = Double.MAX_VALUE;
Double max = Double.MIN_VALUE;
Double v;
List<Double> labels = new ArrayList<Double>();
for (int i = 0; i < nodes.getLength(); i++) {
attribute = nodes.item(i);
if (attribute.getNodeType() == Node.ELEMENT_NODE) {
if (ModuloInfo.LABEL.equals(attribute.getNodeName())) {
v = Double.parseDouble(
attribute.getFirstChild().getNodeValue());
if (v < min) min = v;
if (v > max) max = v;
labels.add(v);
}
}
}
if (!CollectionUtils.isEmpty(labels)) {
info.setStart(min);
info.setEnd(max);
info.setLabels(labels);
}
return info;
}
/**
* Creates a new instance.
*
* @param file The file to parse
*/
public ModuloParser(String file)
{
if (CommonsLangUtils.isEmpty(file))
throw new IllegalArgumentException("No file to parse.");
this.file = file;
modulos = new ArrayList<ModuloInfo>();
moduloTags = new ArrayList<Node>();
}
/**
* Parses the file.
*
* @throws Exception If an error occurs when the annotation cannot be
* parsed.
*/
public void parse()
throws Exception
{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
BufferedWriter out = null;
File f = null;
try {
DocumentBuilder builder = factory.newDocumentBuilder();
f = File.createTempFile("modulo", ".xml");
out = new BufferedWriter(new FileWriter(f));
out.write(file);
out.close();
out = null;
document = builder.parse(f);
readModuloEntries();
Iterator<Node> i = moduloTags.iterator();
Node node;
ModuloInfo entry;
while (i.hasNext()) {
node = i.next();
entry = createModuloFor(node);
if (entry != null) modulos.add(entry);
}
} catch (Exception e) {
throw new Exception("Cannot read the file", e);
} finally {
if (out != null) out.close();
if (f != null) f.delete();
}
}
/**
* Returns the <code>ModuloInfo</code>s.
*
* @return See above.
*/
public List<ModuloInfo> getModulos() { return modulos; }
}