/** * 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.dao.hibernate; import java.math.BigInteger; import java.util.List; import org.hibernate.Criteria; import org.hibernate.Query; import org.hibernate.criterion.DetachedCriteria; import org.hibernate.criterion.Order; import org.hibernate.criterion.Projections; import org.hibernate.criterion.Restrictions; import org.hibernate.criterion.Subqueries; import org.hibernate.sql.JoinType; import org.hibernate.transform.Transformers; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Repository; import fr.mcc.ginco.beans.Alignment; import fr.mcc.ginco.beans.Thesaurus; import fr.mcc.ginco.beans.ThesaurusConcept; import fr.mcc.ginco.beans.ThesaurusConceptGroup; import fr.mcc.ginco.beans.ThesaurusTerm; import fr.mcc.ginco.dao.IThesaurusConceptDAO; import fr.mcc.ginco.enums.ConceptStatusEnum; import fr.mcc.ginco.exceptions.BusinessException; /** * Implementation of the data access object to the thesaurus_term database table */ @Repository public class ThesaurusConceptDAO extends GenericHibernateDAO<ThesaurusConcept, String> implements IThesaurusConceptDAO { private static final String AL_SOURCE_CONCEPT_IDENTIFIER = "al.sourceConcept.identifier"; private static final String TC_IDENTIFIER = "tc.identifier"; private static final String THESAURUS_IDENTIFIER = "thesaurus.identifier"; @Value("${ginco.default.language}") private String defaultLang; public ThesaurusConceptDAO() { super(ThesaurusConcept.class); } /* * (non-Javadoc) * * @see fr.mcc.ginco.dao.IThesaurusConceptDAO#getOrphansThesaurusConcept */ @Override public List<ThesaurusConcept> getOrphansThesaurusConcept( Thesaurus thesaurus, int maxResults) { return getListByThesaurusAndTopConcept(thesaurus, false, maxResults,null,null); } /* * (non-Javadoc) * * @see * fr.mcc.ginco.dao.IThesaurusConceptDAO#getOrphansThesaurusConceptCount * (fr.mcc.ginco.beans.Thesaurus) */ @Override public long getOrphansThesaurusConceptCount(Thesaurus thesaurus) { return getListByThesaurusAndTopConceptCount(thesaurus, false); } /* * (non-Javadoc) * * @see fr.mcc.ginco.dao.IThesaurusConceptDAO#getTopTermThesaurusConcept */ @Override public List<ThesaurusConcept> getTopTermThesaurusConcept( Thesaurus thesaurus, int maxResults,String like) { return getTopTermThesaurusConcept(thesaurus, maxResults, like, null); } @Override public List<ThesaurusConcept> getTopTermThesaurusConcept(Thesaurus thesaurus, int maxResults, String like, ConceptStatusEnum status) { // TODO Auto-generated method stub return getListByThesaurusAndTopConcept(thesaurus, true, maxResults,like, status); } /* * (non-Javadoc) * * @see * fr.mcc.ginco.dao.IThesaurusConceptDAO#getTopTermThesaurusConceptCount * (fr.mcc.ginco.beans.Thesaurus) */ @Override public long getTopTermThesaurusConceptCount(Thesaurus thesaurus) { return getListByThesaurusAndTopConceptCount(thesaurus, true); } @Override public List<ThesaurusConcept> getRootConcepts(String thesaurusId, Boolean searchOrphans) { return getConcepts(null, thesaurusId, searchOrphans, 0,null,null); } @Override public List<String> getIdentifiersOfConceptsWithChildren(String thesaurusId) { Query query = getCurrentSession().createSQLQuery("select tc.identifier" + " from thesaurus_concept tc, hierarchical_relationship hr where" + " hr.parentconceptid = tc.identifier and" + " tc.thesaurusId = :pthesaurusid" + " group by tc.identifier"); query.setParameter("pthesaurusid", thesaurusId); return (List<String>) query.list(); } @Override public List<ThesaurusConcept> getChildrenConcepts(String conceptId, int maxResults,String like, ConceptStatusEnum status) { return getConcepts(conceptId, null, null, maxResults,like, status); } @Override public List<ThesaurusConcept> getChildrenConcepts(String conceptId, int maxResults,String like) { return getConcepts(conceptId, null, null, maxResults,like, null); } private List<ThesaurusConcept> getConcepts(String conceptId, String thesaurusId, Boolean searchOrphans, int maxResults,String like, ConceptStatusEnum status) { Criteria criteria = getCurrentSession().createCriteria(ThesaurusConcept.class, "tc"); if(null != like){ //override previous criteria criteria = getCurrentSession().createCriteria(ThesaurusTerm.class, "tt") .add(Restrictions.isNotNull("tt.concept")) .createCriteria("concept", "tc", JoinType.RIGHT_OUTER_JOIN); criteria.setProjection( Projections .projectionList() .add(Projections.property("tt.lexicalValue")) .add(Projections.property("tc.identifier").as( "identifier"))).setResultTransformer( Transformers.aliasToBean(ThesaurusConcept.class)); conceptNameIsLike(criteria,like); } if ((conceptId != null && !conceptId.isEmpty()) && (thesaurusId != null && !thesaurusId.isEmpty())) { selectRoot(criteria, thesaurusId, conceptId); } else if (conceptId == null || conceptId.isEmpty()) { selectRoot(criteria, thesaurusId); } else { criteria.createCriteria("tc.parentConcepts", "pc").add( Restrictions.eq("pc.identifier", conceptId)); } selectOrphans(criteria, searchOrphans); selectStatus(criteria, status); if (maxResults > 0) criteria.setMaxResults(maxResults); return criteria.list(); } @Override public List<ThesaurusConcept> getConceptsByThesaurusId(String excludeConceptId, String thesaurusId, Boolean searchOrphans, Boolean onlyValidatedConcepts) { Criteria criteria = getCurrentSession().createCriteria( ThesaurusConcept.class, "tc"); selectThesaurus(criteria, thesaurusId); selectOrphans(criteria, searchOrphans); excludeConcept(criteria, excludeConceptId); onlyValidatedConcepts(criteria, onlyValidatedConcepts); return criteria.list(); } @Override public List<ThesaurusConcept> getPaginatedConceptsByThesaurusId( Integer startIndex, Integer limit, String excludeConceptId, String thesaurusId, Boolean searchOrphans, Boolean onlyValidatedConcepts,String like) { Criteria criteria = selectPaginatedConceptsByAlphabeticalOrder(startIndex, limit); selectThesaurus(criteria, thesaurusId); matchLanguage(criteria, thesaurusId); selectOrphans(criteria, searchOrphans); excludeConcept(criteria, excludeConceptId); onlyValidatedConcepts(criteria, onlyValidatedConcepts); conceptNameIsLike(criteria,like); return criteria.list(); } @Override public List<ThesaurusConcept> getPaginatedAvailableConceptsOfGroup( Integer startIndex, Integer limit, String groupId, String thesaurusId, Boolean onlyValidatedConcepts,String like) { DetachedCriteria dc = DetachedCriteria.forClass(ThesaurusConceptGroup.class, "gr"); dc.createCriteria("concepts", "tc", JoinType.RIGHT_OUTER_JOIN); dc.setProjection(Projections.projectionList().add(Projections.property("tc.identifier"))); dc.add(Restrictions.eq("gr.identifier", groupId)); Criteria criteria = selectPaginatedConceptsByAlphabeticalOrder(startIndex, limit); criteria.add(Subqueries.propertyNotIn("tc.identifier", dc)); selectThesaurus(criteria, thesaurusId); criteria.add( Restrictions.not(Restrictions.and( Restrictions.eq("topConcept", false), Restrictions.or(Restrictions.isNull("tc.parentConcepts"), Restrictions.isEmpty("tc.parentConcepts")) ))); if(null != like){ conceptNameIsLike(criteria,like); } onlyValidatedConcepts(criteria, onlyValidatedConcepts); return criteria.list(); } @Override public Long getConceptsByThesaurusIdCount( String excludeConceptId, String thesaurusId, Boolean searchOrphans, Boolean onlyValidatedConcepts,String like) { Criteria criteria = getCurrentSession() .createCriteria(ThesaurusTerm.class, "tt") .add(Restrictions.isNotNull("tt.concept")) .createCriteria("concept", "tc", JoinType.RIGHT_OUTER_JOIN); criteria.add(Restrictions.eq("tt.prefered", Boolean.TRUE)); //criteria.add(Restrictions.eq("tt.language.id", defaultLang)); selectThesaurus(criteria, thesaurusId); selectOrphans(criteria, searchOrphans); excludeConcept(criteria, excludeConceptId); onlyValidatedConcepts(criteria, onlyValidatedConcepts); conceptNameIsLike(criteria,like); criteria.setProjection(Projections.rowCount()); return (Long) criteria.list().get(0); } @Override public List<ThesaurusConcept> getAllRootChildren(ThesaurusConcept concept) { Criteria criteria = getCurrentSession().createCriteria( ThesaurusConcept.class, "tc"); criteria.createCriteria("tc.rootConcepts", "rc").add( Restrictions.eq("rc.identifier", concept.getIdentifier())); return criteria.list(); } private Criteria selectPaginatedConceptsByAlphabeticalOrder(Integer startIndex, Integer limit) { Criteria criteria = getCurrentSession() .createCriteria(ThesaurusTerm.class, "tt") .add(Restrictions.isNotNull("tt.concept")) .createCriteria("concept", "tc", JoinType.RIGHT_OUTER_JOIN); criteria.add(Restrictions.eq("tt.prefered", Boolean.TRUE)); criteria.setProjection( Projections .projectionList() .add(Projections.property("tt.lexicalValue")) .add(Projections.property("tc.identifier").as( "identifier"))).setResultTransformer( Transformers.aliasToBean(ThesaurusConcept.class)); if (limit > 0) { criteria.setMaxResults(limit); } criteria.setFirstResult(startIndex); criteria.addOrder(Order.asc("tt.lexicalValue")); return criteria; } /** * Selects TopTerm concepts by ThesaurusId without excluding. * * @param criteria * @param thesaurusId */ private void selectRoot(Criteria criteria, String thesaurusId) { selectRoot(criteria, thesaurusId, null); } /** * Selects TopTerm concepts by ThesaurusId with excluding. * * @param criteria * @param thesaurusId * @param excludeId */ private void selectRoot(Criteria criteria, String thesaurusId, String excludeId) { excludeConcept(criteria, excludeId); selectThesaurus(criteria, thesaurusId); selectNoParents(criteria); } private void selectNoParents(Criteria criteria) { criteria.add(Restrictions.or(Restrictions.isNull("tc.parentConcepts"), Restrictions.isEmpty("tc.parentConcepts"))); } private void selectThesaurus(Criteria criteria, String thesaurusId) { criteria.add(Restrictions.eq("tc.thesaurus.identifier", (String) thesaurusId)); } private void selectOrphans(Criteria criteria, Boolean searchOrphans) { if (searchOrphans != null) { criteria.add(Restrictions.eq("topConcept", !searchOrphans)); } } private void excludeConcept(Criteria criteria, String excludeId) { if (excludeId != null && !excludeId.isEmpty()) { criteria.add(Restrictions.not(Restrictions.eq(TC_IDENTIFIER, excludeId))); } } private void onlyValidatedConcepts(Criteria criteria, Boolean onlyValidatedConcepts) { if (onlyValidatedConcepts == null) { return; } if (onlyValidatedConcepts) { selectStatus(criteria , ConceptStatusEnum.VALIDATED); } } private void selectStatus (Criteria criteria, ConceptStatusEnum status) { if (status != null) { criteria.add(Restrictions.eq("status", status.getStatus())); } } private void conceptNameIsLike(Criteria criteria,String like) { if (null == like) { return; }else { criteria.add(Restrictions.ilike("tt.lexicalValue","%"+like+"%")); } } private void matchLanguage(Criteria criteria,String thesaurusId) { Criteria thesaurusCriteria = getCurrentSession().createCriteria(Thesaurus.class, "t") .add(Restrictions.eq("t.identifier", thesaurusId)); List<Thesaurus> lThesaurus = thesaurusCriteria.list(); Thesaurus thesaurus = lThesaurus.get(0); criteria.add(Restrictions.in("tt.language", thesaurus.getLang())); } private List<ThesaurusConcept> getListByThesaurusAndTopConcept( Thesaurus thesaurus, boolean topConcept, int maxResults,String like, ConceptStatusEnum status) { if (thesaurus == null) { throw new BusinessException("Object thesaurus can't be null !", "empty-thesaurus"); } Criteria crit = getCriteriaByThesaurusAndTopConcept(thesaurus,topConcept,like, status); if (maxResults > 0) { crit.setMaxResults(maxResults); } return crit.list(); } private long getListByThesaurusAndTopConceptCount(Thesaurus thesaurus, boolean topConcept) { if (thesaurus == null) { throw new BusinessException("Object thesaurus can't be null !", "empty-thesaurus"); } Criteria crit = getCriteriaByThesaurusAndTopConcept(thesaurus, topConcept,null,null).setProjection(Projections.rowCount()); return (Long) crit.list().get(0); } private Criteria getCriteriaByThesaurusAndTopConcept(Thesaurus thesaurus, boolean topConcept,String like, ConceptStatusEnum status) { Criteria criteria = getCurrentSession().createCriteria(ThesaurusConcept.class, "tc"); if(null != like){ criteria = getCurrentSession().createCriteria(ThesaurusTerm.class, "tt") .add(Restrictions.isNotNull("tt.concept")) .createCriteria("concept", "tc", JoinType.RIGHT_OUTER_JOIN); criteria.setProjection( Projections .projectionList() .add(Projections.property("tt.lexicalValue")) .add(Projections.property("tc.identifier").as( "identifier"))).setResultTransformer( Transformers.aliasToBean(ThesaurusConcept.class)); conceptNameIsLike(criteria,like); } selectThesaurus(criteria, thesaurus.getIdentifier()); selectOrphans(criteria, !topConcept); selectNoParents(criteria); selectStatus(criteria, status); return criteria; } @Override public Long countConcepts(String idThesaurus) { Criteria criteria = getCurrentSession().createCriteria( ThesaurusConcept.class); criteria.add(Restrictions.eq(THESAURUS_IDENTIFIER, idThesaurus)) .setProjection(Projections.rowCount()); return (Long) criteria.list().get(0); } @Override public Long countConceptsWoNotes(String idThesaurus) { Query query = getCurrentSession().createSQLQuery( "select count(*) " + "from thesaurus_concept c " + "left join note n on c.identifier = n.conceptid " + "where c.thesaurusid=:pthesaurusid" + " and n.identifier is null" ); query.setParameter("pthesaurusid", idThesaurus); return ((BigInteger) query.list().get(0)).longValue(); } @Override public List<ThesaurusConcept> getConceptsWoNotes(String idThesaurus, int startIndex, int limit) { Query query = getCurrentSession().createSQLQuery("select c.* " + "from thesaurus_concept c " + "left join note n on c.identifier = n.conceptid " + "where c.thesaurusid=:pthesaurusid" + " and n.identifier is null").addEntity(ThesaurusConcept.class); query.setParameter("pthesaurusid", idThesaurus); query.setFirstResult(startIndex); query.setFetchSize(limit); query.setMaxResults(limit); return (List<ThesaurusConcept>) query.list(); } @Override public Long countConceptsAlignedToIntThes(String idThesaurus) { DetachedCriteria alignmentCriteria = DetachedCriteria .forClass(Alignment.class, "al") .add(Restrictions.isNotNull("al.internalTargetThesaurus")) .setProjection( Projections .projectionList() .add(Projections .property(AL_SOURCE_CONCEPT_IDENTIFIER)) ); DetachedCriteria conceptCriteria = DetachedCriteria .forClass(ThesaurusConcept.class, "stc") .add(Restrictions.eq("stc.thesaurus.identifier", idThesaurus)) .setProjection( Projections.projectionList().add( Projections.property("stc.identifier")) ); Criteria criteria = getCurrentSession() .createCriteria(ThesaurusConcept.class, "tc") .add(Restrictions.and( Subqueries.propertyIn(TC_IDENTIFIER, alignmentCriteria), Subqueries.propertyIn(TC_IDENTIFIER, conceptCriteria))) .setProjection(Projections.rowCount()); return (Long) criteria.list().get(0); } @Override public Long countConceptsAlignedToExtThes(String idThesaurus) { DetachedCriteria alignmentCriteria = DetachedCriteria .forClass(Alignment.class, "al") .add(Restrictions.isNotNull("al.externalTargetThesaurus")) .setProjection( Projections .projectionList() .add(Projections .property(AL_SOURCE_CONCEPT_IDENTIFIER)) ); DetachedCriteria conceptCriteria = DetachedCriteria .forClass(ThesaurusConcept.class, "stc") .add(Restrictions.eq("stc.thesaurus.identifier", idThesaurus)) .setProjection( Projections.projectionList().add( Projections.property("stc.identifier")) ); Criteria criteria = getCurrentSession() .createCriteria(ThesaurusConcept.class, "tc") .add(Restrictions.and( Subqueries.propertyIn(TC_IDENTIFIER, alignmentCriteria), Subqueries.propertyIn(TC_IDENTIFIER, conceptCriteria))) .setProjection(Projections.rowCount()); return (Long) criteria.list().get(0); } @Override public Long countConceptsAlignedToMyThes(String idThesaurus) { DetachedCriteria alignmentCriteria = DetachedCriteria .forClass(Alignment.class, "al") .add(Restrictions.eq("al.internalTargetThesaurus.identifier", idThesaurus)) .setProjection( Projections .projectionList() .add(Projections .property(AL_SOURCE_CONCEPT_IDENTIFIER)) ); Criteria criteria = getCurrentSession() .createCriteria(ThesaurusConcept.class, "tc") .add(Subqueries.propertyIn(TC_IDENTIFIER, alignmentCriteria)) .setProjection(Projections.rowCount()); return (Long) criteria.list().get(0); } @Override public List<ThesaurusConcept> getConceptsAlignedToMyThes(String idThesaurus, int startIndex, int limit) { DetachedCriteria alignmentCriteria = DetachedCriteria .forClass(Alignment.class, "al") .add(Restrictions.eq("al.internalTargetThesaurus.identifier", idThesaurus)) .setProjection( Projections .projectionList() .add(Projections .property(AL_SOURCE_CONCEPT_IDENTIFIER)) ); Criteria criteria = getCurrentSession() .createCriteria(ThesaurusConcept.class, "tc") .add(Subqueries.propertyIn(TC_IDENTIFIER, alignmentCriteria)) .setFirstResult(startIndex) .setMaxResults(limit); return (List<ThesaurusConcept>) criteria.list(); } }