/*
* ome.formats.model.ReferenceProcessor
*
*------------------------------------------------------------------------------
* Copyright (C) 2006-2008 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 ome.formats.model;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import ome.formats.Index;
import ome.util.LSID;
import omero.metadatastore.IObjectContainer;
import omero.model.DetectorSettings;
import omero.model.LightPath;
import omero.model.LightSettings;
import omero.model.ObjectiveSettings;
import omero.model.WellSample;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Processes the references of an IObjectContainerStore and ensures
* that container references are consistent with the LSID stored in the
* IObjectContainer itself. It also keeps track of all LSID references
* in their string form so that they may be given to the IObjectContainerStore.
*
* @author Chris Allan <callan at blackcat dot ca>
*
*/
public class ReferenceProcessor implements ModelProcessor {
/** Logger for this class */
private Logger log = LoggerFactory.getLogger(ReferenceProcessor.class);
/* (non-Javadoc)
* @see ome.formats.model.ModelProcessor#process(ome.formats.model.IObjectContainerStore)
*/
public void process(IObjectContainerStore store) throws ModelException {
Map<String, String[]> referenceStringCache =
new HashMap<String, String[]>();
Map<LSID, List<LSID>> referenceCache = store.getReferenceCache();
Map<LSID, IObjectContainer> containerCache = store.getContainerCache();
try {
for (LSID target : referenceCache.keySet()) {
IObjectContainer container = containerCache.get(target);
Class targetClass = target.getJavaClass();
List<String> references = new ArrayList<String>();
for (LSID reference : referenceCache.get(target)) {
if (container == null) {
// Handle the cases where a "Settings" object has been
// used to link an element of the Instrument to the
// Image but there were no acquisition specific
// settings to record. Hence, the "Settings" object
// needs to be created as no MetadataStore methods
// pertaining to the "Settings" object have been entered.
LinkedHashMap<Index, Integer> indexes =
new LinkedHashMap<Index, Integer>();
int[] indexArray = target.getIndexes();
if (targetClass == null) {
log.warn("Unknown target class for LSID: " + target);
references.add(reference.toString());
continue;
} else if (targetClass.equals(DetectorSettings.class)) {
indexes.put(Index.IMAGE_INDEX, indexArray[0]);
indexes.put(Index.CHANNEL_INDEX, indexArray[1]);
} else if (targetClass.equals(LightSettings.class)) {
if (indexArray.length == 2) {
indexes.put(Index.IMAGE_INDEX, indexArray[0]);
indexes.put(Index.CHANNEL_INDEX, indexArray[1]);
} else if (indexArray.length == 3) {
indexes.put(Index.EXPERIMENT_INDEX, indexArray[0]);
indexes.put(
Index.MICROBEAM_MANIPULATION_INDEX, indexArray[1]);
indexes.put(Index.LIGHT_SOURCE_SETTINGS_INDEX, indexArray[2]);
}
} else if (targetClass.equals(ObjectiveSettings.class)) {
indexes.put(Index.IMAGE_INDEX, indexArray[0]);
} else if (targetClass.equals(WellSample.class)) {
// A WellSample has been used to link an Image to
// a Well and there was no acquisition specific
// metadata to record about the WellSample. We now
// need to create it.
indexes.put(Index.PLATE_INDEX, indexArray[0]);
indexes.put(Index.WELL_INDEX, indexArray[1]);
indexes.put(Index.WELL_SAMPLE_INDEX, indexArray[2]);
} else if (targetClass.equals(LightPath.class)) {
// A LightPath has been used to link emission or
// excition filters and / or a dichroic to an
// image. We now need to create it.
indexes.put(Index.IMAGE_INDEX, indexArray[0]);
indexes.put(Index.CHANNEL_INDEX, indexArray[1]);
} else {
throw new RuntimeException(
String.format("Unable to synchronize reference %s --> %s",
reference, target));
}
container = store.getIObjectContainer(targetClass, indexes);
}
// Add our LSIDs to the string based reference cache.
references.add(reference.toString());
}
String lsid = targetClass == null? target.toString() : container.LSID;
// We don't want to overwrite any existing references that may
// have come from other LSID mappings (such as a generated
// LSID) so add any existing LSIDs to the list of references.
if (referenceStringCache.containsKey(lsid)) {
String[] existing = referenceStringCache.get(lsid);
references.addAll(Arrays.asList(existing));
}
String[] referencesAsString =
references.toArray(new String[references.size()]);
referenceStringCache.put(lsid, referencesAsString);
}
store.setReferenceStringCache(referenceStringCache);
}
catch (Exception e) {
throw new ModelException("Error processing references.", null, e);
}
}
}