/*
* 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.codelist.service.internal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import de.fhg.igd.osgi.util.configuration.IConfigurationService;
import de.fhg.igd.osgi.util.configuration.NamespaceConfigurationServiceDecorator;
import eu.esdihumboldt.hale.common.align.model.EntityDefinition;
import eu.esdihumboldt.hale.common.codelist.CodeList;
import eu.esdihumboldt.hale.common.codelist.config.CodeListAssociations;
import eu.esdihumboldt.hale.common.codelist.config.CodeListReference;
import eu.esdihumboldt.hale.common.core.io.Value;
import eu.esdihumboldt.hale.common.core.io.project.ComplexConfigurationService;
import eu.esdihumboldt.hale.ui.codelist.service.CodeListService;
import eu.esdihumboldt.hale.ui.service.project.ProjectService;
import eu.esdihumboldt.hale.ui.service.project.ProjectServiceAdapter;
/**
* Code list service.
*
* @author Kai Schwierczek
* @author Simon Templer
* @partner 01 / Fraunhofer Institute for Computer Graphics Research
*/
public class CodeListServiceImpl implements CodeListService {
/**
* The associated project service.
*/
protected final ProjectService projectService;
/**
* The configuration service to use for storing/loading assignments.
*/
protected final IConfigurationService configurationService;
/**
* The configuration service to use for storing/loading assignments.
*/
protected final ComplexConfigurationService complexConfigService;
/**
* The code list association configuration.
*/
protected volatile CodeListAssociations associations = new CodeListAssociations();
/**
* Constructs this code list service with the given project service. It will
* listen to cleans on the project service to clear all code lists. Also it
* will get/set code list assignments of the current project.
*
* @param projectService the project service
*/
public CodeListServiceImpl(ProjectService projectService) {
this.projectService = projectService;
complexConfigService = projectService.getConfigurationService();
configurationService = new NamespaceConfigurationServiceDecorator(
projectService.getConfigurationService(), "codelist", ":");
projectService.addListener(new ProjectServiceAdapter() {
@Override
public void onClean() {
codelists.clear();
}
@Override
public void afterLoad(ProjectService projectService) {
// update associations from configuration
CodeListAssociations projectAssociations = complexConfigService
.getProperty(CodeListAssociations.KEY_ASSOCIATIONS)
.as(CodeListAssociations.class);
if (projectAssociations != null) {
associations = projectAssociations;
}
else {
associations = new CodeListAssociations();
}
}
});
}
/**
* Maps code list identifiers to code lists.
*/
private final Map<CodeListReference, CodeList> codelists = new HashMap<>();
/**
* Maps resource identifiers to code list identifiers.
*/
private final Map<String, CodeListReference> resourceAssociations = new HashMap<>();
/**
* @see CodeListService#findCodeListByIdentifier(String, String)
*/
@Override
public CodeList findCodeListByIdentifier(String namespace, String identifier) {
CodeListReference key = new CodeListReference(namespace, identifier);
return codelists.get(key);
}
@Override
public CodeList findCodeList(CodeListReference clRef) {
return codelists.get(clRef);
}
/**
* @see CodeListService#getCodeLists()
*/
@Override
public List<CodeList> getCodeLists() {
return new ArrayList<CodeList>(codelists.values());
}
@Override
public CodeList findCodeListByEntity(EntityDefinition entity) {
CodeList result = null;
CodeListReference ref = associations.getCodeList(entity);
if (ref != null) {
result = findCodeListByIdentifier(ref.getNamespace(), ref.getIdentifier());
}
if (result == null) {
// fall-back to legacy mechanism
String ident = entity.getDefinition().getIdentifier();
result = findCodeListByAttribute(ident);
}
return result;
}
@Override
public void assignEntityCodeList(EntityDefinition entity, CodeList code) {
associations.assignCodeList(entity, code);
// update the project configuration
complexConfigService.setProperty(CodeListAssociations.KEY_ASSOCIATIONS,
Value.complex(associations));
}
// public void assignAttributeCodeList(String attributeIdentifier, CodeList code) {
// if (code == null)
// configurationService.set(attributeIdentifier, null);
// else
// configurationService.set(attributeIdentifier,
// code.getNamespace() + "/" + code.getIdentifier());
// }
/**
* Find a code list by attribute identifier.
*
* @param attributeIdentifier the attribute identifier
* @return the code list or <code>null</code>
*/
public CodeList findCodeListByAttribute(String attributeIdentifier) {
String key = configurationService.get(attributeIdentifier);
if (key != null) {
int index = key.lastIndexOf('/');
if (index >= 0) {
String namespace = key.substring(0, index);
String identifier = key.substring(index + 1);
CodeListReference ref = new CodeListReference(namespace, identifier);
return codelists.get(ref);
}
}
return null;
}
@Override
public void addCodeList(String resourceId, CodeList code) {
CodeListReference key = new CodeListReference(code.getNamespace(), code.getIdentifier());
resourceAssociations.put(resourceId, key);
// TODO deal with possible replacements?!
codelists.put(key, code);
}
@Override
public CodeList getCodeList(String resourceId) {
CodeListReference ref = resourceAssociations.get(resourceId);
if (ref != null) {
return codelists.get(ref);
}
return null;
}
@Override
public boolean removeCodeList(String resourceId) {
CodeListReference ref = resourceAssociations.get(resourceId);
if (ref != null) {
if (codelists.remove(ref) != null) {
resourceAssociations.remove(resourceId);
return true;
}
}
return false;
}
}