/*
* Copyright (C) 2006-2016 DLR, Germany
*
* All rights reserved
*
* http://www.rcenvironment.de/
*/
package de.rcenvironment.components.optimizer.gui.view;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.LogFactory;
import de.rcenvironment.components.optimizer.common.Dimension;
import de.rcenvironment.components.optimizer.common.Measure;
import de.rcenvironment.components.optimizer.common.OptimizerReceiver;
import de.rcenvironment.components.optimizer.common.OptimizerResultService;
import de.rcenvironment.components.optimizer.common.OptimizerResultSet;
import de.rcenvironment.components.optimizer.common.ResultSet;
import de.rcenvironment.components.optimizer.common.ResultStructure;
import de.rcenvironment.core.communication.common.ResolvableNodeId;
import de.rcenvironment.core.utils.common.rpc.RemoteOperationException;
/**
* Study holding values generated by the {@link ParametricStudyComponent}.
*
* @author Sascha Zur
*/
public final class OptimizerDatastore extends ResultSet {
private static final long serialVersionUID = 990775937058384209L;
// needed to hold reference otherwise it is can not be called back
private static List<DatasetNotificationSubscriber> notificationSubscriber;
private final List<OptimizerResultSet> datasets = Collections.synchronizedList(new LinkedList<OptimizerResultSet>());
private final List<OptimizerResultSetAddListener> listeners = new LinkedList<OptimizerResultSetAddListener>();
private final Map<String, Double> minValues = new HashMap<String, Double>();
private final Map<String, Double> maxValues = new HashMap<String, Double>();
public OptimizerDatastore(final String identifier, final String title, final ResultStructure structure) {
super(identifier, title, structure);
}
/**
* @param dataset new values.
*/
public void addDataset(final OptimizerResultSet dataset) {
datasets.add(dataset);
fireDatasetAdd(dataset);
for (final Dimension dimension : getStructure().getDimensions()) {
adjustMinMaxRange(dataset, dimension.getName());
}
for (final Measure measure : getStructure().getMeasures()) {
adjustMinMaxRange(dataset, measure.getName());
}
}
private void adjustMinMaxRange(final OptimizerResultSet dataset,
final String key) {
final double value = dataset.getValue(key);
if (minValues.get(key) == null
|| minValues.get(key) > value) {
minValues.put(key, value);
}
if (maxValues.get(key) == null
|| maxValues.get(key) < value) {
maxValues.put(key, value);
}
}
public Collection<OptimizerResultSet> getDatasets() {
return Collections.unmodifiableCollection(datasets);
}
public int getDatasetCount() {
return datasets.size();
}
/**
* @param key of the relevant value chain.
* @return the minimum value of the chain.
*/
public Double getMinValue(final String key) {
return minValues.get(key);
}
/**
* @param key of the relevant value chain.
* @return the maximum value of the chain.
*/
public Double getMaxValue(final String key) {
return maxValues.get(key);
}
/**
* Connects a {@link ResultReceiver} to the {@link StudyPublisher}.
*
* @param identifier the unique identifier
* @param platform the platform to receive updates from
* @param optimizerResultService instance of {@link OptimizerResultService}
* @return created {@link OptimizerDatastore}.
*/
public static OptimizerDatastore connect(final String identifier, final ResolvableNodeId platform,
OptimizerResultService optimizerResultService) {
OptimizerReceiver receiver;
try {
receiver = optimizerResultService.createReceiver(identifier, platform);
if (receiver == null) {
LogFactory.getLog(OptimizerDatastore.class).error("Failed to get values from node: " + platform);
return null;
}
final OptimizerDatastore datastore = new OptimizerDatastore(identifier,
receiver.getStudy().getTitle(), receiver.getStudy().getStructure());
if (notificationSubscriber == null) {
notificationSubscriber = new LinkedList<DatasetNotificationSubscriber>();
}
DatasetNotificationSubscriber newNotificationSubscriber = new DatasetNotificationSubscriber(datastore);
receiver.setNotificationSubscriber(newNotificationSubscriber);
receiver.initialize();
notificationSubscriber.add(newNotificationSubscriber);
return datastore;
} catch (RemoteOperationException e) {
LogFactory.getLog(OptimizerDatastore.class).error("Failed to get values from remote node: " + platform);
}
return null;
}
/**
* @param listener for {@link StudyDataset}to add.
*/
public void addDatasetAddListener(final OptimizerResultSetAddListener listener) {
listeners.add(listener);
}
/**
* @param listener for {@link StudyDataset} to remove.
*/
public void removeDatasetAddListener(final OptimizerResultSetAddListener listener) {
listeners.remove(listener);
}
private void fireDatasetAdd(final OptimizerResultSet dataset) {
final OptimizerResultSetAddListener[] listenersArray = listeners.toArray(new OptimizerResultSetAddListener[0]);
for (final OptimizerResultSetAddListener listener : listenersArray) {
try {
listener.handleStudyDatasetAdd(dataset);
} catch (RuntimeException e) {
e = null; // ignore
}
}
}
/**
* Needs to be implemented by classes which are interested in {@link StudyDataset}.
*
* @author Doreen Seider
*/
public interface OptimizerResultSetAddListener {
/**
* @param dataset the new {@link StudyDataset}.
*/
void handleStudyDatasetAdd(final OptimizerResultSet dataset);
}
}