/*
* Copyright (c) 2013 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:
* Data Harmonisation Panel <http://www.dhpanel.eu>
*/
package eu.esdihumboldt.hale.ui.compatibility.extension.impl;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.ui.PlatformUI;
import de.fhg.igd.eclipse.util.extension.AbstractConfigurationFactory;
import de.fhg.igd.eclipse.util.extension.AbstractExtension;
import de.fhg.igd.eclipse.util.extension.AbstractObjectFactory;
import de.fhg.igd.eclipse.util.extension.ObjectExtension;
import eu.esdihumboldt.cst.internal.CSTCompatibilityMode;
import eu.esdihumboldt.hale.common.align.compatibility.CompatibilityMode;
import eu.esdihumboldt.hale.common.align.model.Cell;
import eu.esdihumboldt.hale.common.filter.definition.CQLFilterDefinition;
import eu.esdihumboldt.hale.common.filter.definition.ECQLFilterDefinition;
import eu.esdihumboldt.hale.ui.HaleUI;
import eu.esdihumboldt.hale.ui.common.service.compatibility.CompatibilityModeFactory;
import eu.esdihumboldt.hale.ui.common.service.compatibility.CompatibilityService;
import eu.esdihumboldt.hale.ui.common.service.compatibility.CompatibilityServiceListener;
import eu.esdihumboldt.hale.ui.compatibility.ProjectExclusiveExtension;
import eu.esdihumboldt.hale.ui.service.align.AlignmentService;
import eu.esdihumboldt.hale.ui.service.align.AlignmentServiceListener;
/**
* Compatibility Service, main class and extension for handling all issues for
* compatibility (e.g. CST or Xslt)
*
* @author Sebastian Reinhardt
*/
@SuppressWarnings("restriction")
public class CompatibilityServiceImpl
extends ProjectExclusiveExtension<CompatibilityMode, CompatibilityModeFactory>
implements CompatibilityService {
// stored listeners of the service
private final CopyOnWriteArraySet<CompatibilityServiceListener> listeners = new CopyOnWriteArraySet<CompatibilityServiceListener>();
private final CompatibilityAlignmentListener cal;
/**
* Default factory based on a configuration element.
*/
private static class CompatibilityModeFactoryImpl extends
AbstractConfigurationFactory<CompatibilityMode>implements CompatibilityModeFactory {
/**
* Create an instance view factory based on a configuration element.
*
* @param conf the configuration element
*/
protected CompatibilityModeFactoryImpl(IConfigurationElement conf) {
super(conf, "class");
}
@Override
public void dispose(CompatibilityMode instance) {
// dispose is handled externally
}
@Override
public String getIdentifier() {
return conf.getAttribute("id");
}
@Override
public String getDisplayName() {
return conf.getAttribute("name");
}
@Override
public Set<String> getSupportedFilters() {
Set<String> result = new HashSet<>();
for (IConfigurationElement filter : conf.getChildren("supportsFilter")) {
String id = filter.getAttribute("ref");
if (id != null) {
result.add(id);
}
}
return result;
}
}
/**
* Default fallback factory
*/
private static class CompatibilityDefaultFactory
extends AbstractObjectFactory<CompatibilityMode>implements CompatibilityModeFactory {
@Override
public CompatibilityMode createExtensionObject() throws Exception {
return new CSTCompatibilityMode();
}
@Override
public void dispose(CompatibilityMode instance) {
// dispose is handled externally
}
@Override
public String getIdentifier() {
return CSTCompatibilityMode.ID;
}
@Override
public String getDisplayName() {
return ("CST Compatibility");
}
@Override
public String getTypeName() {
return CSTCompatibilityMode.class.getName();
}
@Override
public Set<String> getSupportedFilters() {
Set<String> result = new HashSet<>();
result.add(CQLFilterDefinition.ID);
result.add(ECQLFilterDefinition.ID);
return result;
}
}
/**
* default service constructor, also adds a listener to the alignment
* service
*/
public CompatibilityServiceImpl() {
super(new CompatibilityModeExtension(), "compatibilityMode");
cal = new CompatibilityAlignmentListener();
PlatformUI.getWorkbench().getService(AlignmentService.class).addListener(cal);
this.addListener(
new ExclusiveExtensionListener<CompatibilityMode, CompatibilityModeFactory>() {
@Override
public void currentObjectChanged(final CompatibilityMode arg0,
final CompatibilityModeFactory arg1) {
compatibilityModeChanged();
}
});
}
/**
* The extension ID
*/
public static final String EXTENSION_ID = "eu.esdihumboldt.hale.align.compatibility";
/**
* {@link CompatibilityMode} extension
*/
public static class CompatibilityModeExtension
extends AbstractExtension<CompatibilityMode, CompatibilityModeFactory>
implements ObjectExtension<CompatibilityMode, CompatibilityModeFactory> {
/**
* Default constructor
*/
public CompatibilityModeExtension() {
super(EXTENSION_ID);
}
/**
* @see AbstractExtension#createFactory(IConfigurationElement)
*/
@Override
protected CompatibilityModeFactory createFactory(IConfigurationElement conf)
throws Exception {
if (conf.getName().equals("compatibility")) {
return new CompatibilityModeFactoryImpl(conf);
}
return null;
}
}
@Override
protected String getDefaultId() {
return CSTCompatibilityMode.ID;
}
@Override
protected CompatibilityModeFactory getFallbackFactory() {
return new CompatibilityDefaultFactory();
}
/**
* Compatibility Listener for the Alignment
*
* @author Sebastian Reinhardt
*/
class CompatibilityAlignmentListener implements AlignmentServiceListener {
List<Cell> incompatibleCells;
/**
*
*/
public CompatibilityAlignmentListener() {
incompatibleCells = new ArrayList<Cell>();
}
/**
* @see eu.esdihumboldt.hale.ui.service.align.AlignmentServiceListener#alignmentCleared()
*/
@Override
public void alignmentCleared() {
incompatibleCells.clear();
finish();
}
/**
* @see eu.esdihumboldt.hale.ui.service.align.AlignmentServiceListener#cellsAdded(java.lang.Iterable)
*/
@Override
public void cellsAdded(Iterable<Cell> cells) {
CompatibilityMode mode = getCurrent();
Iterator<Cell> cit = cells.iterator();
while (cit.hasNext()) {
Cell cell = cit.next();
boolean isCompatibleNow = mode.supportsFunction(cell.getTransformationIdentifier(),
HaleUI.getServiceProvider()) && mode.supportsCell(cell);
if (!isCompatibleNow) {
incompatibleCells.add(cell);
}
}
finish();
}
/**
* @see eu.esdihumboldt.hale.ui.service.align.AlignmentServiceListener#cellsReplaced(Map)
*/
@Override
public void cellsReplaced(Map<? extends Cell, ? extends Cell> cells) {
CompatibilityMode mode = getCurrent();
for (Entry<? extends Cell, ? extends Cell> e : cells.entrySet()) {
if (incompatibleCells.contains(e.getKey())) {
incompatibleCells.remove(e.getKey());
}
if (!mode.supportsFunction(e.getValue().getTransformationIdentifier(),
HaleUI.getServiceProvider())
|| !mode.supportsCell(e.getValue())) {
incompatibleCells.add(e.getValue());
}
}
finish();
}
/**
* @see eu.esdihumboldt.hale.ui.service.align.AlignmentServiceListener#cellsRemoved(java.lang.Iterable)
*/
@Override
public void cellsRemoved(Iterable<Cell> cells) {
Iterator<Cell> cit = cells.iterator();
while (cit.hasNext()) {
Cell cell = cit.next();
if (incompatibleCells.contains(cell)) {
incompatibleCells.remove(cell);
}
}
finish();
}
/**
* @see eu.esdihumboldt.hale.ui.service.align.AlignmentServiceListener#cellsPropertyChanged(java.lang.Iterable,
* java.lang.String)
*/
@Override
public void cellsPropertyChanged(Iterable<Cell> cells, String propertyName) {
// Do nothing
}
/**
* Completes the checkup after the alignment changes were checked
*/
public void finish() {
if (!incompatibleCells.isEmpty()) {
for (CompatibilityServiceListener listener : listeners) {
listener.compatibilityChanged(false, incompatibleCells);
}
}
if (incompatibleCells.isEmpty())
for (CompatibilityServiceListener listener : listeners) {
listener.compatibilityChanged(true, null);
}
}
@Override
public void customFunctionsChanged() {
// re-evaluate all cells
alignmentChanged();
}
/**
* @see eu.esdihumboldt.hale.ui.service.align.AlignmentServiceListener#alignmentChanged()
*/
@Override
public void alignmentChanged() {
incompatibleCells.clear();
Collection<? extends Cell> cells = PlatformUI.getWorkbench()
.getService(AlignmentService.class).getAlignment().getCells();
Iterator<? extends Cell> cit = cells.iterator();
CompatibilityMode mode = getCurrent();
while (cit.hasNext()) {
Cell cell = cit.next();
boolean isCompatibleNow = mode.supportsFunction(cell.getTransformationIdentifier(),
HaleUI.getServiceProvider()) && mode.supportsCell(cell);
if (!isCompatibleNow) {
incompatibleCells.add(cell);
}
}
finish();
}
}
/**
* @see eu.esdihumboldt.hale.ui.common.service.compatibility.CompatibilityService#addCompatibilityListener(eu.esdihumboldt.hale.ui.common.service.compatibility.CompatibilityServiceListener)
*/
@Override
public void addCompatibilityListener(CompatibilityServiceListener listener) {
listeners.add(listener);
}
/**
* @see eu.esdihumboldt.hale.ui.common.service.compatibility.CompatibilityService#removeCompatibilityListener(CompatibilityServiceListener
* listener)
*/
@Override
public void removeCompatibilityListener(CompatibilityServiceListener listener) {
listeners.remove(listener);
}
/**
* called when the mode is changed (externally, e.g. through user at the ui)
*/
public void compatibilityModeChanged() {
cal.alignmentChanged();
}
}