package hep.aida.ref.root;
import hep.aida.IManagedObject;
import hep.aida.dev.IDevTree;
import hep.aida.dev.IOnDemandStore;
import hep.io.root.RootClassNotFound;
import hep.io.root.RootFileReader;
import hep.io.root.daemon.xrootd.XrootdStreamHandler;
import hep.io.root.interfaces.TDirectory;
import hep.io.root.interfaces.TKey;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.StringTokenizer;
/**
* An implementation of IStore for reading Root files.
* @author tonyj
* @version $Id: XrootdStore.java 8584 2006-08-10 23:06:37Z duns $
*/
class XrootdStore implements IOnDemandStore
{
private RootFileReader file;
private boolean recursive;
private boolean showAllCycles;
private boolean useProxies;
private static URL context;
private static XrootdStreamHandler handler;
private static boolean init = false;
private static void init()
{
try
{
context = new URL("http://www.freehep.org");
}
catch (MalformedURLException x) { /* Won't happen */ }
handler = new XrootdStreamHandler();
init = true;
}
public boolean isReadOnly()
{
return true;
}
public void close() throws IOException
{
if (file != null)
{
file.close();
file = null;
}
}
public void commit(IDevTree tree, Map options) throws IOException
{
throw new UnsupportedOperationException();
}
public void read(IDevTree tree, Map options, boolean readOnly, boolean createNew) throws IOException
{
String storeName = tree.storeName();
if (storeName.startsWith("xroot:"))
{
if (!init) init();
URL url = new URL(context,storeName,handler);
file = new RootFileReader(url,options);
}
else
{
file = new RootFileReader(tree.storeName());
}
useProxies = toBoolean(options,"useProxies");
recursive = toBoolean(options,"recursive");
showAllCycles = toBoolean(options,"showallcycles") || toBoolean(options,"showAllCycles");
if (recursive) addEntries(tree, file, "/");
}
private boolean toBoolean(Map options, String key)
{
Object value = options.get(key);
if (value == null) return false;
return Boolean.valueOf(value.toString()).booleanValue();
}
public void read(IDevTree tree, String path) throws IllegalArgumentException, IOException
{
if (file == null) throw new IOException("Root file is not open.");
TDirectory folder = file;
Object obj = null;
StringTokenizer st = new StringTokenizer(path, "/");
if (st.countTokens()>0)
{
while (st.hasMoreTokens())
{
String token = st.nextToken();
try
{
obj = folder.getKey(token).getObject();
}
catch (RootClassNotFound x)
{
throw new IOException("Root class not found: "+x.getClassName());
}
if (!(obj instanceof TDirectory))
throw new IllegalArgumentException("Path "+path+" does not point to a directory in the ROOT file "+tree.storeName());
folder = (TDirectory) obj;
}
}
addEntries(tree, folder, path);
}
private void addEntries(IDevTree tree, TDirectory dir, String path) throws IOException
{
if (showAllCycles)
{
int nKeys = dir.nKeys();
for (int k = 0; k < nKeys; k++)
{
addEntry(tree,path,dir.getKey(k));
}
}
else
{
// Find only the latest cycle for each key
HashMap map = new HashMap();
int nKeys = dir.nKeys();
for (int k = 0; k < nKeys; k++)
{
TKey key = dir.getKey(k);
String name = key.getName();
TKey oldKey = (TKey) map.get(name);
if (oldKey == null || key.getCycle() > oldKey.getCycle()) map.put(name,key);
}
for (Iterator i = map.values().iterator(); i.hasNext(); )
{
addEntry(tree,path, (TKey) i.next());
}
}
tree.hasBeenFilled(path);
}
private void addEntry(IDevTree tree, String path, TKey key) throws IOException
{
try
{
if (TDirectory.class.isAssignableFrom(key.getObjectClass().getJavaClass()))
{
String newPath;
if (path.endsWith("/"))
newPath = path + key.getName();
else
newPath = path + "/" + key.getName();
tree.mkdirs(newPath);
if (recursive) addEntries(tree, (TDirectory) key.getObject(), newPath);
}
else
{
IManagedObject im = Converter.convert(key, getName(key), useProxies);
if (im != null)
tree.add(path,im);
}
}
catch (RootClassNotFound x)
{
throw new IOException("Root class not found: "+x.getClassName());
}
}
private String getName(TKey key)
{
return showAllCycles ? key.getName() + ";" + key.getCycle() : key.getName();
}
}