/*
* 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.views.tasks.model.providers.schema;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import eu.esdihumboldt.hale.mapping.helper.EntityHelper;
import eu.esdihumboldt.hale.schemaprovider.model.AttributeDefinition;
import eu.esdihumboldt.hale.schemaprovider.model.Definition;
import eu.esdihumboldt.hale.schemaprovider.model.SchemaElement;
import eu.esdihumboldt.hale.schemaprovider.model.TypeDefinition;
import eu.esdihumboldt.hale.ui.service.mapping.AlignmentService;
import eu.esdihumboldt.hale.ui.service.mapping.AlignmentServiceAdapter;
import eu.esdihumboldt.hale.ui.service.schema.SchemaService;
import eu.esdihumboldt.hale.ui.service.schema.SchemaService.SchemaType;
import eu.esdihumboldt.hale.ui.service.schema.SchemaServiceAdapter;
import eu.esdihumboldt.hale.ui.views.tasks.model.Task;
import eu.esdihumboldt.hale.ui.views.tasks.model.impl.AbstractTaskProvider;
import eu.esdihumboldt.hale.ui.views.tasks.service.TaskService;
import eu.esdihumboldt.specification.cst.align.ICell;
import eu.esdihumboldt.specification.cst.align.IEntity;
/**
* Schema based task provider. Reacts on changes to schema and removed alignment
* cells.
*
* @author Simon Templer
* @partner 01 / Fraunhofer Institute for Computer Graphics Research
*/
public abstract class AbstractSchemaTaskProvider extends AbstractTaskProvider {
private final SchemaType schemaType;
private SchemaService schemaService;
private SchemaServiceAdapter schemaListener;
private AlignmentService alignmentService;
private AlignmentServiceAdapter alignmentListener;
private boolean reactOnCellAddOrUpdate = false;
/**
* Create a new schema task provider for the given schema type
*
* @param prefix the type name prefix or <code>null</code>
* @param schemaType the schema type
*/
public AbstractSchemaTaskProvider(String prefix, SchemaType schemaType) {
super(prefix);
this.schemaType = schemaType;
}
/**
* @param reactOnCellAddOrUpdate the reactOnCellAddOrUpdate to set
*/
public void setReactOnCellAddOrUpdate(boolean reactOnCellAddOrUpdate) {
this.reactOnCellAddOrUpdate = reactOnCellAddOrUpdate;
}
/**
* @return the schemaType
*/
public SchemaType getSchemaType() {
return schemaType;
}
/**
* @see AbstractTaskProvider#doActivate(TaskService)
*/
@Override
protected void doActivate(final TaskService taskService) {
schemaService = serviceProvider.getService(SchemaService.class);
alignmentService = serviceProvider.getService(AlignmentService.class);
// create tasks from the current schema
generateSchemaTasks(taskService, schemaService.getSchema(schemaType));
// create tasks for new schema types
schemaService.addListener(schemaListener = new SchemaServiceAdapter() {
@Override
public void schemaChanged(SchemaType schema) {
if (schema.equals(schemaType)) {
generateSchemaTasks(taskService, schemaService.getSchema(schema));
}
}
});
// create tasks when cells have been removed
alignmentService.addListener(alignmentListener = new AlignmentServiceAdapter() {
@Override
public void alignmentCleared() {
generateSchemaTasks(taskService, schemaService.getSchema(schemaType));
}
@Override
public void cellRemoved(ICell cell) {
generateSchemaTasks(cell, false); //XXX
}
@Override
public void cellsAdded(Iterable<ICell> cells) {
if (reactOnCellAddOrUpdate) {
for (ICell cell : cells) {
generateSchemaTasks(cell, true); //XXX
}
}
}
@Override
public void cellsUpdated(Iterable<ICell> cells) {
if (reactOnCellAddOrUpdate) {
for (ICell cell : cells) {
generateSchemaTasks(cell, true); //XXX
}
}
}
});
}
/**
* Generate schema tasks based on the given cell
*
* @param cell the cell
* @param checkSuperTypes if super types shall be checked
*/
protected void generateSchemaTasks(ICell cell, boolean checkSuperTypes) {
// get entity
IEntity entity;
switch (schemaType) {
case SOURCE:
entity = cell.getEntity1();
break;
case TARGET:
entity = cell.getEntity2();
break;
default:
throw new RuntimeException("Invalid schema type"); //$NON-NLS-1$
}
// get definition
String identifier = EntityHelper.getIdentifier(entity);
Definition definition = schemaService.getDefinition(identifier, schemaType);
if (definition != null) {
if (definition instanceof SchemaElement) {
// type mapping removed
if (checkSuperTypes) {
Collection<SchemaElement> elements = new ArrayList<SchemaElement>();
TypeDefinition type = ((SchemaElement) definition).getType();
while (type != null) {
elements.addAll(type.getDeclaringElements());
type = type.getSuperType();
}
generateSchemaTasks(taskService, elements);
}
else {
generateSchemaTasks(taskService, Collections.singleton((SchemaElement) definition));
}
}
else if (definition instanceof AttributeDefinition) {
Collection<Task> tasks = new ArrayList<Task>();
AttributeDefinition attribute = (AttributeDefinition) definition;
generateAttributeTasks(attribute, tasks);
taskService.addTasks(tasks);
}
}
}
/**
* Generate schema tasks
*
* @param taskService the task service
* @param schema the schema
*/
protected void generateSchemaTasks(TaskService taskService,
Collection<SchemaElement> schema) {
Collection<Task> tasks = new ArrayList<Task>();
for (SchemaElement element : schema) {
if (element.getType().isFeatureType()) { // restrict to feature types FIXME really? maybe this should be configurable
// create type tasks
generateElementTasks(element, tasks);
// create attribute tasks
for (AttributeDefinition attribute : element.getType().getDeclaredAttributes()) {
generateAttributeTasks(attribute, tasks);
}
}
}
taskService.addTasks(tasks);
}
/**
* Generate tasks based on the given attribute
*
* @param attribute the attribute
* @param taskList the task list to add created tasks to
*/
protected abstract void generateAttributeTasks(AttributeDefinition attribute,
Collection<Task> taskList);
/**
* Generate tasks based on the given element
*
* @param element the element
* @param taskList the task list to add created tasks to
*/
protected abstract void generateElementTasks(SchemaElement element,
Collection<Task> taskList);
/**
* @see AbstractTaskProvider#doDeactivate()
*/
@Override
protected void doDeactivate() {
if (schemaListener != null) {
schemaService.removeListener(schemaListener);
}
if (alignmentListener!= null) {
alignmentService.removeListener(alignmentListener);
}
}
}