/*
* Copyright (c) 2012 Diamond Light Source Ltd.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package uk.ac.diamond.scisoft.analysis.io;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.dawnsci.analysis.api.io.IDataHolder;
import org.eclipse.dawnsci.analysis.api.io.IFileLoader;
import org.eclipse.dawnsci.analysis.api.io.ILoaderService;
import org.eclipse.dawnsci.analysis.api.metadata.IDiffractionMetadata;
import org.eclipse.january.IMonitor;
import org.eclipse.january.dataset.IDataset;
import org.eclipse.january.dataset.ILazyDataset;
import org.eclipse.january.metadata.AxesMetadata;
import org.eclipse.january.metadata.IMetadata;
import org.eclipse.january.metadata.MetadataFactory;
/**
* Provides a class which will use any loaders available to load a particular file
*
* TODO FIXME This class should be moved to a proper OSGI service.
*
* @author gerring
*
*/
public class LoaderServiceImpl implements ILoaderService {
static {
System.out.println("Starting loader service");
}
public LoaderServiceImpl() {
// Important do nothing here, OSGI may start the service more than once.
}
@Override
public IDataHolder getData(String filePath, final IMonitor monitor) throws Exception {
return getData(filePath, false, monitor);
}
@Override
public IDataHolder getData(String filePath, boolean lazily, IMonitor monitor) throws Exception {
IMonitor mon = monitor!=null ? monitor : new IMonitor.Stub();
return LoaderFactory.getData(filePath, true, false, lazily, mon);
}
@Override
public IDataset getDataset(String filePath, final IMonitor monitor) throws Exception {
try {
final URL uri = new URL(filePath);
filePath = uri.getPath();
} catch (Throwable ignored) {
// We try the file path anyway
}
IMonitor mon = monitor!=null ? monitor : new IMonitor.Stub();
final IDataHolder dh = LoaderFactory.getData(filePath, mon);
return dh!=null ? dh.getDataset(0) : null;
}
@Override
public IDataset getDataset(final String path, final String datasetName, final IMonitor monitor) throws Exception {
IMonitor mon = monitor!=null ? monitor : new IMonitor.Stub();
return LoaderFactory.getDataSet(path, datasetName, mon);
}
@Override
public IMetadata getMetadata(final String filePath, final IMonitor monitor) throws Exception {
IMonitor mon = monitor!=null ? monitor : new IMonitor.Stub();
return LoaderFactory.getMetadata(filePath, mon);
}
private IDiffractionMetadata lockedDiffractionMetaData;
@Override
public IDiffractionMetadata getLockedDiffractionMetaData() {
return lockedDiffractionMetaData;
}
@Override
public IDiffractionMetadata setLockedDiffractionMetaData(IDiffractionMetadata diffMetaData) {
IDiffractionMetadata old = lockedDiffractionMetaData;
lockedDiffractionMetaData= diffMetaData;
LoaderFactory.setLockedMetaData(lockedDiffractionMetaData); // The locking can change meta of original data.
return old;
}
@Override
public Collection<String> getSupportedExtensions() {
return LoaderFactory.getSupportedExtensions();
}
@Override
public void clearSoftReferenceCache() {
LoaderFactory.clear();
}
@Override
public void clearSoftReferenceCache(String filePath) {
LoaderFactory.clear(filePath);
}
@Override
public Matcher getStackMatcher(String name) {
int posExt = name.lastIndexOf(".");
if (posExt>-1) {
String regexp = LoaderFactory.getStackExpression();
String ext = name.substring(posExt + 1);
Pattern pattern = Pattern.compile(regexp+"\\.("+ext+")");
return pattern.matcher(name);
}
return null;
}
@Override
public AxesMetadata getAxesMetadata(ILazyDataset parent, String path, List<String>[] axesNames, boolean lazy) throws Exception {
AxesMetadata axMeta = null;
int rank = parent.getRank();
axMeta = MetadataFactory.createMetadata(AxesMetadata.class, rank);
if (axesNames == null) return axMeta;
if (axesNames.length != rank) throw new IllegalArgumentException("Array of name lists must be equal in length to the rank of the dataset");
int[] shape = parent.getShape();
IDataHolder dataHolder = getData(path, null);
for (int j = 0; j < axesNames.length; j++) {
if (axesNames[j] == null) continue;
for (String name : axesNames[j]) {
if (name == null) continue;
ILazyDataset lazyDataset = dataHolder.getLazyDataset(name);
if (lazyDataset == parent) throw new IllegalArgumentException("Axes metadata should not contain original dataset!");
if (lazyDataset!= null) {
lazyDataset.setName(name);
int axRank = lazyDataset.getRank();
if (axRank == rank || axRank == 1) {
lazyDataset = lazyDataset.getSliceView();
lazyDataset.clearMetadata(AxesMetadata.class);
axMeta.addAxis(j, lazy ? lazyDataset : lazyDataset.getSlice());
} else {
int[] axShape = lazyDataset.getShape();
int[] newShape = new int[rank];
Arrays.fill(newShape, 1);
int[] idx = new int[axRank];
Arrays.fill(idx, -1);
Boolean[] found = new Boolean[axRank];
Arrays.fill(found, false);
int max = rank;
for (int i = axRank-1; i >= 0; i--) {
int id = axShape[i];
updateShape(i, max, shape, id, idx, found);
}
boolean allFound = !Arrays.asList(found).contains(false);
if (!allFound) {
throw new IllegalArgumentException("Axes shape not compatible!");
}
for (int i = 0; i < axRank; i++) {
newShape[idx[i]] = axShape[i];
}
lazyDataset = lazyDataset.getSliceView();
lazyDataset.clearMetadata(AxesMetadata.class);
lazyDataset.setShape(newShape);
axMeta.addAxis(j, lazy ? lazyDataset : lazyDataset.getSlice(),idx);
}
}
else {
axMeta.setAxis(j, new ILazyDataset[1]);
}
}
}
return axMeta;
}
@Override
public AxesMetadata getAxesMetadata(ILazyDataset parent, String path, Map<Integer, String> axesNames, boolean lazy) throws Exception {
List<String>[] axesNameLists = new List[parent.getRank()];
for (Integer key : axesNames.keySet()) {
if (axesNameLists[key-1] == null) {
axesNameLists[key-1] = new ArrayList<String>();
}
axesNameLists[key-1].add(axesNames.get(key));
}
return getAxesMetadata(parent, path, axesNameLists, lazy);
}
private boolean updateShape(int i, int max, int[] shape, int id, int[] idx, Boolean[] found){
int[] idxc = idx.clone();
Arrays.sort(idxc);
for (int j = max -1 ; j >= 0; j--) {
if (id == shape[j] && Arrays.binarySearch(idxc, j) < 0) {
idx[i] = j;
found[i] = true;
max = j;
return true;
}
}
return false;
}
@Override
public Class<? extends IFileLoader> getLoaderClass(String extension) {
return LoaderFactory.getLoaderClass(extension);
}
}