/**
* Copyright or © or Copr. Ministère Français chargé de la Culture
* et de la Communication (2013)
* <p/>
* contact.gincoculture_at_gouv.fr
* <p/>
* This software is a computer program whose purpose is to provide a thesaurus
* management solution.
* <p/>
* This software is governed by the CeCILL license under French law and
* abiding by the rules of distribution of free software. You can use,
* modify and/ or redistribute the software under the terms of the CeCILL
* license as circulated by CEA, CNRS and INRIA at the following URL
* "http://www.cecill.info".
* <p/>
* As a counterpart to the access to the source code and rights to copy,
* modify and redistribute granted by the license, users are provided only
* with a limited warranty and the software's author, the holder of the
* economic rights, and the successive licensors have only limited liability.
* <p/>
* In this respect, the user's attention is drawn to the risks associated
* with loading, using, modifying and/or developing or reproducing the
* software by the user in light of its specific status of free software,
* that may mean that it is complicated to manipulate, and that also
* therefore means that it is reserved for developers and experienced
* professionals having in-depth computer knowledge. Users are therefore
* encouraged to load and test the software's suitability as regards their
* requirements in conditions enabling the security of their systemsand/or
* data to be ensured and, more generally, to use and operate it in the
* same conditions as regards security.
* <p/>
* The fact that you are presently reading this means that you have had
* knowledge of the CeCILL license and that you accept its terms.
*/
package fr.mcc.ginco.imports;
import com.hp.hpl.jena.ontology.ObjectProperty;
import com.hp.hpl.jena.rdf.model.Resource;
import fr.mcc.ginco.beans.*;
import fr.mcc.ginco.dao.IAlignmentDAO;
import fr.mcc.ginco.dao.IAssociativeRelationshipDAO;
import fr.mcc.ginco.dao.IConceptHierarchicalRelationshipDAO;
import fr.mcc.ginco.dao.IExternalThesaurusDAO;
import fr.mcc.ginco.dao.IGenericDAO;
import fr.mcc.ginco.dao.INoteDAO;
import fr.mcc.ginco.dao.IThesaurusConceptDAO;
import fr.mcc.ginco.dao.IThesaurusTermDAO;
import fr.mcc.ginco.exceptions.BusinessException;
import fr.mcc.ginco.services.IConceptHierarchicalRelationshipServiceUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import javax.inject.Inject;
import javax.inject.Named;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Builder in charge of building ThesaurusConcept
*/
@Service("skosConceptsBuilder")
public class ConceptsBuilder extends AbstractBuilder {
private static Logger logger = LoggerFactory.getLogger(ConceptsBuilder.class);
@Inject
private IThesaurusConceptDAO thesaurusConceptDAO;
@Inject
private IAssociativeRelationshipDAO associativeRelationshipDAO;
@Inject
private IConceptHierarchicalRelationshipDAO conceptHierarchicalRelationshipDAO;
@Inject
private IThesaurusTermDAO thesaurusTermDAO;
@Inject
private INoteDAO noteDAO;
@Inject
@Named("skosConceptBuilder")
private ConceptBuilder conceptBuilder;
@Inject
@Named("skosConceptNoteBuilder")
private ConceptNoteBuilder conceptNoteBuilder;
@Inject
private IAlignmentDAO alignmentDAO;
@Inject
private IGenericDAO<AlignmentConcept, Integer> alignmentConceptDAO;
@Inject
private IGenericDAO<AlignmentResource, Integer> alignmentResourceDAO;
@Inject
private IExternalThesaurusDAO externalThesaurusDAO;
@Inject
@Named("skosAlignmentsBuilder")
private AlignmentsBuilder alignmentsBuilder;
@Inject
@Named("skosTermBuilder")
private TermBuilder termBuilder;
@Inject
@Named("conceptHierarchicalRelationshipServiceUtil")
private IConceptHierarchicalRelationshipServiceUtil conceptHierarchicalRelationshipServiceUtil;
/**
* Launch the calculation of the root concepts and set it
*
* @param thesaurus
* @param skosConcepts
*/
public void buildConceptsRoot(Thesaurus thesaurus,
List<Resource> skosConcepts) {
for (Resource skosConcept : skosConcepts) {
// Root calculation
ThesaurusConcept concept = conceptBuilder.buildConceptRoot(
skosConcept, thesaurus);
thesaurusConceptDAO.update(concept);
}
}
/**
* Builds the parent/child and relationship associations
*
* @param thesaurus
* @param skosConcepts
*/
public void buildConceptsAssociations(Thesaurus thesaurus,
List<Resource> skosConcepts, List<ObjectProperty> broaderTypes, List<ObjectProperty> associationTypes) {
List<AssociativeRelationship> allRelations = new ArrayList<AssociativeRelationship>();
int counter = 1;
Set<String> alreadyImported = new HashSet<String>();
for (Resource skosConcept : skosConcepts) {
if (counter % 100 == 0) {
logger.info("Processed " + skosConcepts.size() + "/" + counter + " relationships");
}
Map<ThesaurusConcept, List<ConceptHierarchicalRelationship>> relationsThesaurusConcept = conceptBuilder
.buildConceptHierarchicalRelationships(skosConcept,
thesaurus, broaderTypes);
if (relationsThesaurusConcept.keySet().iterator().hasNext()) {
ThesaurusConcept concept = relationsThesaurusConcept.keySet()
.iterator().next();
for (ConceptHierarchicalRelationship relation : relationsThesaurusConcept.get(concept)) {
String parentChildId = relation.getIdentifier().getParentconceptid() + relation.getIdentifier().getChildconceptid();
if (alreadyImported.contains(parentChildId)) {
conceptHierarchicalRelationshipDAO.update(relation);
alreadyImported.add(parentChildId);
}
}
}
Set<AssociativeRelationship> associativeRelationships = conceptBuilder
.buildConceptAssociativerelationship(skosConcept, thesaurus, associationTypes);
for (AssociativeRelationship relation : associativeRelationships) {
Boolean isRelationAdded = false;
for (AssociativeRelationship existedRelation : allRelations) {
if (existedRelation.getConceptLeft().equals(
relation.getConceptRight())
&& existedRelation.getConceptRight().equals(
relation.getConceptLeft())
|| existedRelation.equals(relation)) {
isRelationAdded = true;
}
}
if (!isRelationAdded) {
allRelations.add(relation);
associativeRelationshipDAO.update(relation);
}
}
counter++;
}
thesaurusConceptDAO.flush();
}
/**
* Builds the concept with minimal informations and it's terms and notes
*
* @param thesaurus
* @param skosConcepts
*/
public Set<Alignment> buildConcepts(Thesaurus thesaurus,
List<Resource> skosConcepts) {
Set<Alignment> bannedAlignments = new HashSet<Alignment>();
Set<String> importedLexicalValues = new HashSet<String>();
int counter = 1;
List<ExternalThesaurus> lExternalThesaurusUpdated = new LinkedList<ExternalThesaurus>();
logger.info("Beginning importing " + skosConcepts.size() + " concepts");
for (Resource skosConcept : skosConcepts) {
if (counter % 100 == 0) {
logger.info("Imported " + skosConcepts.size() + "/" + counter + " concepts");
}
// Minimal concept informations
ThesaurusConcept concept = conceptBuilder.buildConcept(skosConcept,
thesaurus);
thesaurusConceptDAO.update(concept);
ThesaurusTerm preferredTerm = null;
// Concept terms
List<ThesaurusTerm> terms = termBuilder.buildTerms(skosConcept,
thesaurus, concept);
for (ThesaurusTerm term : terms) {
String langLexicalValue = term.getLexicalValue() + term.getLanguage().getId();
if (term.getPrefered()) {
preferredTerm = term;
}
if (!importedLexicalValues.contains(langLexicalValue)) {
thesaurusTermDAO.update(term, false);
importedLexicalValues.add(langLexicalValue);
} else {
throw new BusinessException("Already existing term : "
+ term.getLexicalValue(), "already-existing-term",
new Object[]{ term.getLexicalValue() }
);
}
}
// Concept notes
List<Note> conceptNotes = conceptNoteBuilder.buildConceptNotes(
skosConcept, concept, preferredTerm, thesaurus);
for (Note conceptNote : conceptNotes) {
noteDAO.update(conceptNote);
}
// Concept alignments and External Thesaurus
List<Alignment> alignments = alignmentsBuilder.buildAlignments(skosConcept, concept);
ExternalThesaurus externalThesaurusToSet = null;
for (Alignment alignment : alignments) {
externalThesaurusToSet = null;
//ExternalThesaurus already updated in base ?
if (alignment.getExternalTargetThesaurus() != null) {
ExternalThesaurus externalThesaurusHere = alignment.getExternalTargetThesaurus();
//ExternalThesaurus already updated in base ?
int i = 0;
while(null == externalThesaurusToSet && i < lExternalThesaurusUpdated.size()){
ExternalThesaurus externalThesaurusUpdated = lExternalThesaurusUpdated.get(i);
if(externalThesaurusUpdated.getExternalId().equals(externalThesaurusHere.getExternalId())){
if(externalThesaurusUpdated.getExternalThesaurusType() == externalThesaurusHere.getExternalThesaurusType()){
externalThesaurusToSet = externalThesaurusUpdated;
}
}
i++;
}
//ExternalThesaurus already in base ? (if not updated)
if(null == externalThesaurusToSet){
List<ExternalThesaurus> lExternalsThesaurusMatchOnBase = externalThesaurusDAO.getByExternalId(externalThesaurusHere.getExternalId());
int j =0;
while(null == externalThesaurusToSet && j < lExternalsThesaurusMatchOnBase.size()){
ExternalThesaurus externalThesaurusMatchOnBase = lExternalsThesaurusMatchOnBase.get(j);
if(externalThesaurusMatchOnBase.getExternalThesaurusType() == externalThesaurusHere.getExternalThesaurusType()){
externalThesaurusToSet = externalThesaurusMatchOnBase;
}
j++;
}
}
//ExternalThesaurus update in base (if not already done and not already present)
if(null == externalThesaurusToSet){
externalThesaurusToSet = externalThesaurusDAO.update(alignment.getExternalTargetThesaurus());
lExternalThesaurusUpdated.add(externalThesaurusToSet);
}
alignment.setExternalTargetThesaurus(externalThesaurusToSet);
}
if (alignment.getInternalTargetThesaurus() != null || alignment.getExternalTargetThesaurus() != null || alignment.getTargetResources().size() != 0 ) {
for (AlignmentConcept alignmentConcept : alignment.getTargetConcepts()) {
alignmentConceptDAO.update(alignmentConcept);
}
for (AlignmentResource alignmentResource : alignment.getTargetResources()) {
alignmentResourceDAO.update(alignmentResource);
}
alignmentDAO.update(alignment);
} else {
bannedAlignments.add(alignment);
}
}
counter++;
}
thesaurusTermDAO.flush();
return bannedAlignments;
}
}