/*
* Copyright (c) 2012 Data Harmonisation Panel
*
* All rights reserved. This program and the accompanying materials are made
* available under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution. If not, see <http://www.gnu.org/licenses/>.
*
* Contributors:
* HUMBOLDT EU Integrated Project #030962
* Data Harmonisation Panel <http://www.dhpanel.eu>
*/
package eu.esdihumboldt.hale.ui.service.instance.internal;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArraySet;
import eu.esdihumboldt.hale.common.align.model.Cell;
import eu.esdihumboldt.hale.common.align.transformation.service.TransformationService;
import eu.esdihumboldt.hale.common.core.HalePlatform;
import eu.esdihumboldt.hale.common.core.io.Value;
import eu.esdihumboldt.hale.common.core.io.project.ProjectVariables;
import eu.esdihumboldt.hale.common.instance.model.DataSet;
import eu.esdihumboldt.hale.ui.service.align.AlignmentService;
import eu.esdihumboldt.hale.ui.service.align.AlignmentServiceAdapter;
import eu.esdihumboldt.hale.ui.service.instance.InstanceService;
import eu.esdihumboldt.hale.ui.service.instance.InstanceServiceListener;
import eu.esdihumboldt.hale.ui.service.project.ProjectService;
import eu.esdihumboldt.hale.ui.service.project.ProjectServiceAdapter;
import eu.esdihumboldt.util.groovy.sandbox.GroovyService;
import eu.esdihumboldt.util.groovy.sandbox.GroovyServiceListener;
/**
* Notification handling for {@link InstanceService}s that support
* {@link InstanceServiceListener}s
*
* @author Simon Templer
* @partner 01 / Fraunhofer Institute for Computer Graphics Research
*/
public abstract class AbstractInstanceService implements InstanceService {
private final CopyOnWriteArraySet<InstanceServiceListener> listeners = new CopyOnWriteArraySet<InstanceServiceListener>();
private final AlignmentService alignmentService;
private final ProjectService projectService;
private boolean liveTransform = true; // TODO where to store the
// configuration? project?
/**
* Create an instance service.
*
* @param projectService the project service. The instances will be cleared
* when the project is cleaned.
* @param alignmentService the alignment service
* @param groovyService the groovy service
*/
public AbstractInstanceService(ProjectService projectService, AlignmentService alignmentService,
GroovyService groovyService) {
super();
this.alignmentService = alignmentService;
this.projectService = projectService;
projectService.addListener(new ProjectServiceAdapter() {
@Override
public void onClean() {
clearInstances();
}
@Override
public void projectSettingChanged(String name, Value value) {
if (ProjectVariables.PROJECT_PROPERTY_VARIABLES.equals(name)) {
// project variables changed
retransform();
}
}
});
alignmentService.addListener(new AlignmentServiceAdapter() {
@Override
public void alignmentCleared() {
clearTransformedInstances();
}
@Override
public void cellsRemoved(Iterable<Cell> cells) {
/*
* TODO analyze cell if it is a type or property mapping
* property mapping: retransform based on related type mappings
* type mapping: removed transformed instances based on type
* mapping
*/
retransform();
}
@Override
public void cellsReplaced(Map<? extends Cell, ? extends Cell> cells) {
/*
* TODO only retransform with relevant cells (i.e. create a view
* on the alignment)
*/
retransform();
}
@Override
public void cellsAdded(Iterable<Cell> cells) {
/*
* TODO only retransform with relevant cells (i.e. create a view
* on the alignment)
*/
retransform();
}
@Override
public void customFunctionsChanged() {
retransform();
}
@Override
public void alignmentChanged() {
retransform();
}
@Override
public void cellsPropertyChanged(Iterable<Cell> cells, String propertyName) {
/*
* TODO only retransform with relevant cells (i.e. create a view
* on the alignment)
*/
retransform();
}
});
groovyService.addListener(new GroovyServiceListener() {
@Override
public void restrictionChanged(boolean restrictionActive) {
retransform();
}
});
}
/**
* @see InstanceService#setTransformationEnabled(boolean)
*/
@Override
public void setTransformationEnabled(boolean enabled) {
if (enabled != liveTransform) {
liveTransform = enabled; // XXX use a lock for liveTransform?
if (enabled) {
retransform();
}
else {
clearTransformedInstances();
}
notifyTransformationToggled(enabled);
}
}
/**
* @see InstanceService#isTransformationEnabled()
*/
@Override
public boolean isTransformationEnabled() {
return liveTransform;
}
/**
* Retransform all instances. Decides if a transformation should be done or
* not.
*/
protected final void retransform() {
if (isTransformationEnabled()) {
doRetransform();
}
}
/**
* Retransform all instances.
*/
protected abstract void doRetransform();
/**
* Clear the transformed instances
*/
protected abstract void clearTransformedInstances();
/**
* @return the transformationService
*/
protected TransformationService getTransformationService() {
return HalePlatform.getService(TransformationService.class);
}
/**
* @return the alignmentService
*/
protected AlignmentService getAlignmentService() {
return alignmentService;
}
/**
* @return the projectService
*/
protected ProjectService getProjectService() {
return projectService;
}
/**
* Called when the transformation has been enabled or disabled.
*
* @param enabled if the transformation is enabled now
*/
public void notifyTransformationToggled(boolean enabled) {
for (InstanceServiceListener listener : listeners) {
listener.transformationToggled(enabled);
}
}
/**
* Notify listeners that a data set has changed
*
* @param type the data set type, <code>null</code> if both sets have
* changed
*/
protected void notifyDatasetChanged(DataSet type) {
for (InstanceServiceListener listener : listeners) {
if (type == null) {
listener.datasetChanged(DataSet.SOURCE);
listener.datasetChanged(DataSet.TRANSFORMED);
}
else {
listener.datasetChanged(type);
}
}
}
/**
* Notify listeners that a data set is about to be changed
*
* @param type the data set type, <code>null</code> if both sets will change
*/
protected void notifyDatasetAboutToChange(DataSet type) {
for (InstanceServiceListener listener : listeners) {
if (type == null) {
listener.datasetAboutToChange(DataSet.SOURCE);
listener.datasetAboutToChange(DataSet.TRANSFORMED);
}
else {
listener.datasetAboutToChange(type);
}
}
}
// /**
// * Notify listeners that the CRS has changed
// *
// * @param crs the new CRS definition
// */
// protected void notifyCRSChanged(CRSDefinition crs) {
// for (InstanceServiceListener listener : listeners) {
// listener.crsChanged(crs);
// }
// }
@Override
public void addListener(InstanceServiceListener listener) {
listeners.add(listener);
}
@Override
public void removeListener(InstanceServiceListener listener) {
listeners.remove(listener);
}
}