001package fr.ifremer.adagio.core.dao.referential.taxon;
002
003/*
004 * #%L
005 * SIH-Adagio :: Core
006 * $Id: TaxonNameDaoImpl.java 12089 2014-05-20 19:37:05Z bl05b3e $
007 * $HeadURL: https://forge.ifremer.fr/svn/sih-adagio/tags/adagio-3.5.6/core/src/main/java/fr/ifremer/adagio/core/dao/referential/taxon/TaxonNameDaoImpl.java $
008 * %%
009 * Copyright (C) 2012 - 2013 Ifremer
010 * %%
011 * This program is free software: you can redistribute it and/or modify
012 * it under the terms of the GNU Affero General Public License as published by
013 * the Free Software Foundation, either version 3 of the License, or
014 * (at your option) any later version.
015 * 
016 * This program is distributed in the hope that it will be useful,
017 * but WITHOUT ANY WARRANTY; without even the implied warranty of
018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
019 * GNU General Public License for more details.
020 * 
021 * You should have received a copy of the GNU Affero General Public License
022 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
023 * #L%
024 */
025
026import java.util.ArrayList;
027import java.util.Collection;
028import java.util.Date;
029import java.util.Iterator;
030import java.util.List;
031
032import javax.annotation.Resource;
033
034import org.hibernate.Query;
035import org.hibernate.Session;
036import org.springframework.beans.factory.annotation.Autowired;
037import org.springframework.dao.DataRetrievalFailureException;
038import org.springframework.stereotype.Repository;
039
040import com.google.common.base.Function;
041import com.google.common.collect.Multimap;
042import com.google.common.collect.Multimaps;
043
044import fr.ifremer.adagio.core.dao.referential.StatusCode;
045import fr.ifremer.adagio.core.dao.technical.hibernate.TemporaryDataHelper;
046
047/**
048 * @see fr.ifremer.adagio.core.dao.referential.taxon.TaxonName
049 */
050@Repository("taxonNameDao")
051public class TaxonNameDaoImpl
052        extends fr.ifremer.adagio.core.dao.referential.taxon.TaxonNameDaoBase
053        implements TaxonNameExtendDao {
054
055    private static final String QUERY_ALL_TAXON = "allTaxonNames";
056
057    private static final String QUERY_ALL_TAXON_IS_REFERENT = "allTaxonNamesIsReferent";
058
059    private static final String QUERY_TAXON_NAME_REFERENT = "taxonNameReferent";
060
061    private static final String QUERY_ALL_TAXON_WITH_TRANSCRIBING = "allTaxonNamesWithTranscribing";
062
063    private static final String QUERY_ALL_TAXON_IS_REFERENT_WITH_TRANSCRIBING = "allTaxonNamesIsReferentWithTranscribing";
064
065    private static final String QUERY_TAXON_NAME_REFERENT_WITH_TRANSCRIBING = "taxonNameReferentWithTranscribing";
066    private static final String QUERY_ALL_TRANSCRIBING_FOR_A_TYPE = "allTranscribingForAType";
067
068    @Resource(name = "referenceTaxonDao")
069    protected ReferenceTaxonDao referenceTaxonDao;
070
071    /** Constructor used by Spring */
072    @Autowired
073    public TaxonNameDaoImpl(org.hibernate.SessionFactory sessionFactory) {
074        super();
075        setSessionFactory(sessionFactory);
076    }
077
078    @Override
079    public TaxonRefVO[] getAllTaxonNames(boolean withSynonyms) {
080        return getAllTaxonNames(withSynonyms, null);
081    }
082
083    // FIXME-TC Make this works again within a single request
084    @Override
085    public TaxonRefVO[] getAllTaxonNames(boolean withSynonyms,
086            Integer transcribingId) {
087        try {
088
089            Session session = getSession();
090
091            Query query;
092
093            boolean withTranscribing = transcribingId != null;
094
095            // if (withTranscribing) {
096            //
097            // // with transcribing
098            // if (withSynonyms) {
099            // query = session.getNamedQuery(QUERY_ALL_TAXON_WITH_TRANSCRIBING);
100            // } else {
101            // query = session.getNamedQuery(QUERY_ALL_TAXON_IS_REFERENT_WITH_TRANSCRIBING);
102            // }
103            // query.setInteger("transcribingTypeId", transcribingId);
104            // } else {
105            //
106            // // with no transcribing
107            // if (withSynonyms) {
108            // query = session.getNamedQuery(QUERY_ALL_TAXON);
109            // } else {
110            // query = session.getNamedQuery(QUERY_ALL_TAXON_IS_REFERENT);
111            // }
112            // }
113
114            if (withSynonyms) {
115                query = session.getNamedQuery(QUERY_ALL_TAXON);
116            } else {
117                query = session.getNamedQuery(QUERY_ALL_TAXON_IS_REFERENT);
118            }
119
120            List<TaxonRefVO> results = new ArrayList<TaxonRefVO>();
121            for (Iterator<Object[]> iterator = query.iterate(); iterator.hasNext();) {
122                Object[] cols = iterator.next();
123                TaxonRefVO taxonNameRefTaxVO = loadTaxon(cols, false);
124                results.add(taxonNameRefTaxVO);
125            }
126            if (results.size() == 0) {
127                return null;
128            }
129
130            if (withTranscribing) {
131                query = session.getNamedQuery(QUERY_ALL_TRANSCRIBING_FOR_A_TYPE);
132                query.setInteger("transcribingTypeId", transcribingId);
133
134                Multimap<Integer, TaxonRefVO> r = Multimaps.index(results, new Function<TaxonRefVO, Integer>() {
135                    @Override
136                    public Integer apply(fr.ifremer.adagio.core.dao.referential.taxon.TaxonRefVO input) {
137                        return input.getReferenceTaxonId();
138                    }
139                });
140
141                for (Iterator<Object[]> iterator = query.iterate(); iterator.hasNext();) {
142                    Object[] cols = iterator.next();
143                    Integer referencetaxonId = (Integer) cols[0];
144                    String externalCode = (String) cols[1];
145                    Collection<TaxonRefVO> taxonRefVOs = r.get(referencetaxonId);
146                    if (taxonRefVOs != null)
147                        for (TaxonRefVO taxonRefVO : taxonRefVOs) {
148                            taxonRefVO.setExternalCode(externalCode);
149                        }
150                }
151            }
152
153            // Return the first element in the list
154            return results.toArray(new TaxonRefVO[results.size()]);
155        } catch (RuntimeException re) {
156            logger.error("getAllTaxonNames failed", re); //$NON-NLS-1$
157            throw re;
158        }
159    }
160
161    @Override
162    public TaxonRefVO getTaxonNameReferent(Integer referenceTaxonId) {
163        return getTaxonNameReferent(referenceTaxonId, null);
164    }
165
166    @Override
167    public TaxonRefVO getTaxonNameReferent(Integer referenceTaxonId,
168            Integer transcribingId) {
169        boolean withTranscribing = transcribingId != null;
170        try {
171
172            Session session = getSession();
173
174            Query query;
175            if (withTranscribing) {
176
177                query = session.getNamedQuery(QUERY_TAXON_NAME_REFERENT_WITH_TRANSCRIBING);
178                query.setInteger("transcribingTypeId", transcribingId);
179            } else {
180                query = session.getNamedQuery(QUERY_TAXON_NAME_REFERENT);
181            }
182            query.setInteger("referenceTaxonId", referenceTaxonId);
183
184            Object[] cols = (Object[]) query.uniqueResult();
185            if (cols == null) {
186                throw new DataRetrievalFailureException("TaxonName with referenceTaxonId=" + referenceTaxonId + " could not found.");
187            }
188            TaxonRefVO result = loadTaxon(cols, withTranscribing);
189
190            return result;
191        } catch (RuntimeException re) {
192            logger.error("getTaxonNameReferent failed", re); //$NON-NLS-1$
193            throw re;
194        }
195    }
196
197    @Override
198    public TaxonRefVO createAsTemporary(TaxonRefVO taxonNameVO, String comments) {
199        if (taxonNameVO == null) {
200            throw new IllegalArgumentException("Argument 'taxonName' could not be null.");
201        }
202        if (taxonNameVO.getName() == null || taxonNameVO.getName().isEmpty()) {
203            throw new IllegalArgumentException("Argument 'taxonName.name' could not be null or empty.");
204        }
205        logger.debug("call create(taxonName)"); //$NON-NLS-1$
206        try {
207
208            Session session = getSession();
209
210            // Generate a new id for referenceTaxon
211            Integer referenceTaxonId = TemporaryDataHelper.getNewNegativeIdForTemporaryData(session, ReferenceTaxonImpl.class);
212            Integer taxonNameId = TemporaryDataHelper.getNewNegativeIdForTemporaryData(session, TaxonNameImpl.class);
213
214            ReferenceTaxon referenceTaxon = ReferenceTaxon.Factory.newInstance();
215            referenceTaxon.setId(referenceTaxonId);
216            referenceTaxon.setName(TemporaryDataHelper.TEMPORARY_NAME_PREFIX + taxonNameVO.getName());
217
218            referenceTaxon = referenceTaxonDao.create(referenceTaxon);
219
220            TaxonName taxonName = TaxonName.Factory.newInstance();
221            taxonName.setId(taxonNameId);
222            taxonName.setIsTemporary(true);
223            taxonName.setIsReferent(true);
224            taxonName.setIsObsolete(false);
225            taxonName.setReferenceTaxon(referenceTaxon);
226            taxonName.setName(TemporaryDataHelper.TEMPORARY_NAME_PREFIX + taxonNameVO.getName());
227            taxonName.setIsNaming(false);
228            taxonName.setIsVirtual(false);
229            taxonName.setStartDate(new Date());
230            taxonName.setCreationDate(new Date());
231            taxonName.setUpperRank(1);
232
233            // Taxonomic level
234            TaxonomicLevel speciesTaxonomicLevel = (TaxonomicLevel) session.load(TaxonomicLevelImpl.class, TaxonomicLevelCode.SPECIES.getValue());
235            taxonName.setTaxonomicLevel(speciesTaxonomicLevel);
236
237            // Compute the comments with RefTaxCode (if present)
238            StringBuffer commentsBuffer = new StringBuffer();
239            if (taxonNameVO.getExternalCode() != null) {
240                commentsBuffer.append(taxonNameVO.getExternalCode());
241            }
242            if (comments != null && !comments.isEmpty()) {
243                if (commentsBuffer.length() > 0) {
244                    commentsBuffer.append(" - ");
245                }
246                commentsBuffer.append(comments);
247            }
248            taxonName.setComments(commentsBuffer.toString());
249
250            // Create the TaxonName
251            create(taxonName);
252
253            // Fill the result VO
254            TaxonRefVO result = new TaxonRefVO();
255            result.setName(taxonNameVO.getName());
256            result.setExternalCode(taxonNameVO.getExternalCode());
257            result.setReferenceTaxonId(referenceTaxonId);
258            result.setTaxonNameId(taxonNameId);
259            result.setIsReference(true);
260            result.setStatus(StatusCode.TEMPORARY);
261
262            return result;
263        } catch (RuntimeException re) {
264            logger.error("create(taxonName) failed", re); //$NON-NLS-1$
265            throw re;
266        }
267    }
268
269    // ------------------------------------------------------------------------//
270    // -- Internal methods --//
271    // ------------------------------------------------------------------------//
272
273    protected TaxonRefVO loadTaxon(Object[] cols, boolean withTranscribing) {
274        TaxonRefVO result = new TaxonRefVO();
275        int colIndex = 0;
276
277        // ReferenceTaxon.id
278        result.setReferenceTaxonId((Integer) cols[colIndex++]);
279
280        // TaxonName.id
281        result.setTaxonNameId((Integer) cols[colIndex++]);
282
283        // Is reference
284        result.setIsReference((Boolean) cols[colIndex++]);
285
286        // TaxonName.name (remove temp prefix if present)
287        String name = (String) cols[colIndex++];
288        if (name != null && name.startsWith(TemporaryDataHelper.TEMPORARY_NAME_PREFIX)) {
289            name = name.substring(TemporaryDataHelper.TEMPORARY_NAME_PREFIX.length());
290        }
291        result.setName(name);
292
293        // Status :
294        Boolean tempStatus = (Boolean) cols[colIndex++];
295        StatusCode status = tempStatus ? StatusCode.TEMPORARY : StatusCode.ENABLE;
296        result.setStatus(status);
297
298        if (withTranscribing) {
299            String externalCode = (String) cols[colIndex];
300            result.setExternalCode(externalCode);
301        }
302        return result;
303    }
304}