/*
* #%L
* OME Bio-Formats manual and automated test suite.
* %%
* Copyright (C) 2006 - 2015 Open Microscopy Environment:
* - Board of Regents of the University of Wisconsin-Madison
* - Glencoe Software, Inc.
* - University of Dundee
* %%
* 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, see
* <http://www.gnu.org/licenses/gpl-2.0.html>.
* #L%
*/
package loci.tests.testng;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.StringTokenizer;
import javax.swing.tree.DefaultMutableTreeNode;
import loci.common.Constants;
import loci.common.IniList;
import loci.common.IniParser;
import loci.common.IniTable;
import loci.common.Location;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Stores configuration data about files in a directory structure.
* This class is not designed to be thread safe, so should be synchronized
* externally for proper thread safety.
*/
public class ConfigurationTree {
// -- Constants --
private static final Logger LOGGER =
LoggerFactory.getLogger(ConfigurationTree.class);
// -- Fields --
/** Directory on the file system associated with the tree root. */
private String rootDir;
/** Base directory on the file system associated with the configuration
* files.
*/
private String configDir;
/**
* Root of tree structure containing configuration data.
* Each node's user object is a hashtable of key/value pairs.
*/
private DefaultMutableTreeNode root;
// -- Constructor --
/**
* Constructs a new configuration tree rooted at the given directory in the
* file system.
*
* @param rootDir a string specifying the root directory
*
*/
public ConfigurationTree(String rootDir) {
this(rootDir, null);
}
/**
* Constructs a new configuration tree rooted at the given directory in the
* file system with a custom configuration directory.
*
* @param rootDir a string specifying the root directory
* @param configDir a string specifying the base configuration directory
*
*/
public ConfigurationTree(String rootDir, String configDir) {
if (rootDir == null) {
throw new IllegalArgumentException("rootDir cannot be null.");
}
if (configDir != null) {
Location rootLocation = new Location(rootDir);
Location configLocation = new Location(configDir);
while (rootLocation.getName().equals(configLocation.getName())) {
rootLocation = rootLocation.getParentFile();
configLocation = configLocation.getParentFile();
}
this.rootDir = rootLocation.getAbsolutePath();
this.configDir = configLocation.getAbsolutePath();
} else {
this.rootDir = new File(rootDir).getAbsolutePath();
}
root = new DefaultMutableTreeNode();
}
// -- ConfigurationTree API methods --
/**
* Returns the toot directory holding the data
*/
public String getRootDirectory() {
return this.rootDir;
}
/**
* Returns the base directory holding the configuration files
*/
public String getConfigDirectory() {
return this.configDir;
}
/**
* Relocate a path from an base directory into a target directory
*/
public String relocate(String path, String oldRoot, String newRoot) {
String subPath = path.substring((int) Math.min(
oldRoot.length() + 1, path.length()));
if (subPath.length() == 0) {
return newRoot;
}
else {
return new Location(newRoot, subPath).getAbsolutePath();
}
}
/**
* Relocate a path under the root directory to the configuration directory
*/
public String relocateToConfig(String path) {
return relocate(path, this.rootDir, this.configDir);
}
/**
* Relocate a path under the configuration directory to the root directory
*/
public String relocateToRoot(String path) {
return relocate(path, this.configDir, this.rootDir);
}
/** Retrieves the Configuration object corresponding to the given file. */
public Configuration get(String id) throws IOException {
DefaultMutableTreeNode pos = findNode(id, false, null);
if (pos == null) return null;
Hashtable table = (Hashtable) pos.getUserObject();
return (Configuration) table.get("configuration");
}
public void parseConfigFile(String configFile) throws IOException {
File file = new File(configFile);
if (file.isDirectory()) {
return;
}
String parent = file.getParent();
if (configDir != null) {
parent = relocateToRoot(parent);
}
configFile = file.getAbsolutePath();
String dir = file.getParentFile().getAbsolutePath();
IniParser parser = new IniParser();
parser.setCommentDelimiter(null);
FileInputStream stream = new FileInputStream(configFile);
IniList iniList = parser.parseINI(new BufferedReader(
new InputStreamReader(stream, Constants.ENCODING)));
for (IniTable table : iniList) {
String id = table.get(IniTable.HEADER_KEY);
id = id.substring(0, id.lastIndexOf(" "));
id = new File(parent, id).getAbsolutePath();
DefaultMutableTreeNode node = findNode(id, true, configFile);
if (node == null) {
LOGGER.warn("config file '{}' has invalid filename '{}'",
configFile, id);
continue;
}
}
}
// -- Helper methods --
/** Gets the tree node associated with the given file. */
private DefaultMutableTreeNode findNode(String id, boolean create, String configFile) {
String baseID = id;
if (!id.startsWith(rootDir)) return null;
id = id.substring(rootDir.length());
StringTokenizer st = new StringTokenizer(id, "\\/");
DefaultMutableTreeNode node = root;
while (st.hasMoreTokens()) {
String token = st.nextToken();
Enumeration en = node.children();
DefaultMutableTreeNode next = null;
while (en.hasMoreElements()) {
DefaultMutableTreeNode child =
(DefaultMutableTreeNode) en.nextElement();
Hashtable table = (Hashtable) child.getUserObject();
if (token.equals(table.get("name"))) {
next = child;
break;
}
}
if (next == null) {
// create node, if applicable
if (!create) return null;
next = new DefaultMutableTreeNode();
Hashtable table = new Hashtable();
table.put("name", token);
try {
table.put("configuration", new Configuration(baseID, configFile));
}
catch (IOException e) { }
next.setUserObject(table);
node.add(next);
}
node = next;
}
return node;
}
}