com.gisgraphy.domain.repository.AdmDao.java Source code

Java tutorial

Introduction

Here is the source code for com.gisgraphy.domain.repository.AdmDao.java

Source

/*******************************************************************************
 *   Gisgraphy Project 
 * 
 *   This library is free software; you can redistribute it and/or
 *   modify it under the terms of the GNU Lesser General Public
 *   License as published by the Free Software Foundation; either
 *   version 2.1 of the License, or (at your option) any later version.
 * 
 *   This library is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 *   Lesser General Public License for more details.
 * 
 *   You should have received a copy of the GNU Lesser General Public
 *   License along with this library; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
 * 
 *  Copyright 2008  Gisgraphy project 
 *  David Masclet <davidmasclet@gisgraphy.com>
 *  
 *  
 *******************************************************************************/
package com.gisgraphy.domain.repository;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.PersistenceException;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.stereotype.Repository;
import org.springframework.util.Assert;

import com.gisgraphy.domain.geoloc.entity.Adm;
import com.gisgraphy.domain.geoloc.entity.GisFeature;

/**
 * A data access object for {@link Adm}
 * 
 * @author <a href="mailto:david.masclet@gisgraphy.com">David Masclet</a>
 */
@Repository
public class AdmDao extends GenericGisDao<Adm> implements IAdmDao {

    public AdmDao() {
        super(Adm.class);
    }

    @Override
    public Adm get(final Long id) {
        Assert.notNull(id, "Can not retrieve an Ogject with a null id");
        Adm returnValue = null;
        try {
            return (Adm) this.getHibernateTemplate().execute(new HibernateCallback() {

                public Object doInHibernate(Session session) throws PersistenceException {
                    String queryString = "from " + persistentClass.getSimpleName() + " o where o.id=" + id;

                    Query qry = session.createQuery(queryString);
                    qry.setCacheable(true);
                    return (Adm) qry.uniqueResult();

                }
            });
        } catch (Exception e) {
            logger.info("could not retrieve object of type " + persistentClass.getSimpleName() + " with id " + id,
                    e);
        }
        return returnValue;
    }

    /**
     * Check that codes are consistent according the level (see
     * {@link Adm#isConsistentForLevel() } and save it in the datastore
     * 
     * @param adm
     *                The Adm to save
     * @return the saved instance
     * @see Adm#isConsistentForLevel()
     */
    @Override
    public Adm save(Adm adm) {
        if (!adm.isConsistentForLevel()) {
            throw new RuntimeException("Level and AdmXCode are inconsistant for " + adm.toString());
        }
        return super.save(adm);
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.gisgraphy.domain.repository.IAdmDao#getAdm1(java.lang.String,
     *      java.lang.String)
     */
    public Adm getAdm1(final String countryCode, final String adm1Code) {
        Assert.notNull(countryCode);
        Assert.notNull(adm1Code);
        return (Adm) this.getHibernateTemplate().execute(new HibernateCallback() {

            public Object doInHibernate(Session session) throws PersistenceException {
                String queryString = "from " + Adm.class.getSimpleName()
                        + " as a where a.countryCode = ? and a.adm1Code= ? and a.level=1";

                Query qry = session.createQuery(queryString);
                qry.setCacheable(true);

                qry.setParameter(0, countryCode.toUpperCase());
                qry.setParameter(1, adm1Code);

                Adm result = (Adm) qry.uniqueResult();

                return result;
            }
        });
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.gisgraphy.domain.repository.IAdmDao#getAdm2(java.lang.String,
     *      java.lang.String, java.lang.String)
     */
    public Adm getAdm2(final String countryCode, final String adm1Code, final String adm2Code) {
        Assert.notNull(countryCode);
        Assert.notNull(adm1Code);
        Assert.notNull(adm2Code);

        return (Adm) this.getHibernateTemplate().execute(new HibernateCallback() {

            public Object doInHibernate(Session session) throws PersistenceException {
                String queryString = "from " + Adm.class.getSimpleName()
                        + " as a where a.countryCode=? and a.adm2Code=?";
                if (!"00".equals(adm1Code)) {
                    queryString += "and a.adm1Code= ?";
                }
                queryString += " and a.level=2";

                Query qry = session.createQuery(queryString);
                qry.setCacheable(true);

                qry.setParameter(0, countryCode.toUpperCase());
                qry.setParameter(1, adm2Code);
                if (!"00".equals(adm1Code)) {
                    qry.setParameter(2, adm1Code);
                }

                Adm result;
                try {
                    result = (Adm) qry.uniqueResult();
                } catch (HibernateException e) {
                    if (!"00".equals(adm1Code)) {
                        throw e;
                    } else {
                        logger.error("Can not retrieve Adm for countrycode=" + countryCode + " and adm2code="
                                + adm2Code + " in flex mode : result is ambiguous");
                        return null;
                    }
                }

                return result;
            }
        });
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.gisgraphy.domain.repository.IAdmDao#getAdm3(java.lang.String,
     *      java.lang.String, java.lang.String, java.lang.String)
     */
    public Adm getAdm3(final String countryCode, final String adm1Code, final String adm2Code,
            final String adm3Code) {
        Assert.notNull(countryCode);
        Assert.notNull(adm1Code);
        Assert.notNull(adm2Code);
        Assert.notNull(adm3Code);
        return (Adm) this.getHibernateTemplate().execute(new HibernateCallback() {

            public Object doInHibernate(Session session) throws PersistenceException {
                String queryString = "from " + Adm.class.getSimpleName()
                        + " as a where a.countryCode=? and a.adm2Code=? and a.adm3Code=?";
                if (!"00".equals(adm1Code)) {
                    queryString += "and a.adm1Code= ?";
                }
                queryString += " and a.level=3";

                Query qry = session.createQuery(queryString);
                qry.setCacheable(true);

                qry.setParameter(0, countryCode.toUpperCase());
                qry.setParameter(1, adm2Code);
                qry.setParameter(2, adm3Code);

                if (!"00".equals(adm1Code)) {
                    qry.setParameter(3, adm1Code);
                }

                Adm result;
                try {
                    result = (Adm) qry.uniqueResult();
                } catch (HibernateException e) {
                    if (!"00".equals(adm1Code)) {
                        throw e;
                    } else {
                        logger.error("Can not retrieve Adm for countrycode=" + countryCode + " and adm2code="
                                + adm2Code + " and adm3code=" + adm3Code + " in flex mode : result is ambiguous");
                        return null;
                    }
                }

                return result;
            }
        });
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.gisgraphy.domain.repository.IAdmDao#getAdm4(java.lang.String,
     *      java.lang.String, java.lang.String, java.lang.String,
     *      java.lang.String)
     */
    public Adm getAdm4(final String countryCode, final String adm1Code, final String adm2Code,
            final String adm3Code, final String adm4Code) {
        Assert.notNull(countryCode);
        Assert.notNull(adm1Code);
        Assert.notNull(adm2Code);
        Assert.notNull(adm3Code);
        Assert.notNull(adm4Code);

        return (Adm) this.getHibernateTemplate().execute(new HibernateCallback() {

            public Object doInHibernate(Session session) throws PersistenceException {
                String queryString = "from " + Adm.class.getSimpleName()
                        + " as a where a.countryCode=? and a.adm2Code=? and a.adm3Code=? and a.adm4Code=?";
                if (!"00".equals(adm1Code)) {
                    queryString += "and a.adm1Code= ?";
                }
                queryString += " and a.level=4";

                Query qry = session.createQuery(queryString);
                qry.setCacheable(true);

                qry.setParameter(0, countryCode.toUpperCase());
                qry.setParameter(1, adm2Code);
                qry.setParameter(2, adm3Code);
                qry.setParameter(3, adm4Code);

                if (!"00".equals(adm1Code)) {
                    qry.setParameter(4, adm1Code);
                }

                Adm result;
                try {
                    result = (Adm) qry.uniqueResult();
                } catch (HibernateException e) {
                    if (!"00".equals(adm1Code)) {
                        throw e;
                    } else {
                        logger.error("Can not retrieve Adm for countrycode=" + countryCode + " and adm2code="
                                + adm2Code + " and adm3code=" + adm3Code + " and adm4code=" + adm4Code
                                + " in flex mode : result is ambiguous");
                        return null;
                    }
                }

                return result;
            }
        });
    }

    private boolean isAdmCodeEmpty(String admCode) {
        if (admCode == null || admCode.trim().equals("")) {
            return true;
        }
        return false;
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.gisgraphy.domain.repository.IAdmDao#getAdm(java.lang.String,
     *      java.lang.String, java.lang.String, java.lang.String,
     *      java.lang.String)
     */
    public Adm getAdm(final String countryCode, final String adm1Code, final String adm2Code, final String adm3Code,
            final String adm4Code) {
        Assert.notNull(countryCode);
        if (!isAdmCodeEmpty(countryCode)) {
            if (!isAdmCodeEmpty(adm1Code)) {
                if (!isAdmCodeEmpty(adm2Code)) {
                    if (!isAdmCodeEmpty(adm3Code)) {
                        if (!isAdmCodeEmpty(adm4Code)) {
                            // adm1,adm2,adm3,adm4
                            return getAdm4(countryCode, adm1Code, adm2Code, adm3Code, adm4Code);
                        } else {
                            // adm1,adm2,adm3,null
                            return getAdm3(countryCode, adm1Code, adm2Code, adm3Code);
                        }
                    } else {
                        // adm1,Adm2, null..
                        return getAdm2(countryCode, adm1Code, adm2Code);
                    }
                } else {
                    // adm1,null...
                    return getAdm1(countryCode, adm1Code);
                }
            } else {
                logger.info("Can not retrieve an adm if Adm1code is null");
                // if adm1 is empty can not retrieve any Adm
                return null;
            }
        } else {
            return null;
        }

    }

    /*
     * (non-Javadoc)
     * 
     * @see com.gisgraphy.domain.repository.IAdmDao#getUnused()
     */
    @SuppressWarnings("unchecked")
    public List<Adm> getUnused() {
        return (List<Adm>) this.getHibernateTemplate().execute(new HibernateCallback() {

            public Object doInHibernate(final Session session) throws PersistenceException {
                final String queryString = "from " + Adm.class.getSimpleName()
                        + " as a where a not in (select distinct(g.adm) from GisFeature g)";

                final Query qry = session.createQuery(queryString);
                qry.setCacheable(true);

                List<Adm> result = qry.list();
                if (result == null) {
                    result = new ArrayList<Adm>();
                }

                return result;
            }
        });
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.gisgraphy.domain.repository.GenericGisDao#getDirty()
     */
    @Override
    @SuppressWarnings("unchecked")
    public List<Adm> getDirties() {
        return (List<Adm>) this.getHibernateTemplate().execute(new HibernateCallback() {

            public Object doInHibernate(final Session session) throws PersistenceException {
                final String queryString = "from " + Adm.class.getSimpleName() + " as a where a.featureId < 0";

                final Query qry = session.createQuery(queryString);
                qry.setCacheable(true);

                List<Adm> result = qry.list();
                if (result == null) {
                    result = new ArrayList<Adm>();
                }

                return result;
            }
        });
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.gisgraphy.domain.repository.IAdmDao#getAllbyLevel(java.lang.Integer)
     */
    @SuppressWarnings("unchecked")
    public List<Adm> getAllbyLevel(final int level) {
        return (List<Adm>) this.getHibernateTemplate().execute(new HibernateCallback() {

            public Object doInHibernate(final Session session) throws PersistenceException {
                final String queryString = "from " + Adm.class.getSimpleName() + " as a where a.level=?";

                final Query qry = session.createQuery(queryString);
                qry.setCacheable(true);

                qry.setParameter(0, level);

                List<Adm> result = qry.list();
                if (result == null) {
                    result = new ArrayList<Adm>();
                }

                return result;
            }
        });
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.gisgraphy.domain.repository.IAdmDao#countByLevel(int)
     */
    public long countByLevel(final int level) {
        // level is of type int =>could not be null
        return ((Long) this.getHibernateTemplate().execute(new HibernateCallback() {

            public Object doInHibernate(Session session) throws PersistenceException {
                String queryString = "select count(*) from " + Adm.class.getSimpleName() + " a where a.level=? ";

                Query qry = session.createQuery(queryString);
                qry.setCacheable(true);
                qry.setParameter(0, level);

                Long result = (Long) qry.uniqueResult();
                return result;
            }
        })).longValue();
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.gisgraphy.domain.repository.IAdmDao#getAdmByCountryAndCodeAndLevel(java.lang.String,
     *      java.lang.String, int)
     */
    @SuppressWarnings("unchecked")
    public List<Adm> getAdmByCountryAndCodeAndLevel(final String countryCode, final String admCode,
            final int level) {
        Assert.notNull(countryCode);
        Assert.notNull(admCode);
        // level is a int =>can not be null
        return (List<Adm>) this.getHibernateTemplate().execute(new HibernateCallback() {

            public Object doInHibernate(Session session) throws PersistenceException {
                String queryString = "from " + Adm.class.getSimpleName() + " as a where  a.countryCode= ? and a.adm"
                        + level + "Code = ?  and a.level=?";

                Query qry = session.createQuery(queryString);
                qry.setCacheable(true);

                qry.setParameter(0, countryCode.toUpperCase());
                qry.setParameter(1, admCode);
                qry.setParameter(2, level);

                List<Adm> result = (List<Adm>) qry.list();
                if (result == null) {
                    return new ArrayList<Adm>();
                }
                return result;
            }
        });
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.gisgraphy.domain.repository.IAdmDao#getAdmOrFirstValidParentIfNotFound(java.lang.String,
     *      java.lang.String, java.lang.String, java.lang.String,
     *      java.lang.String)
     */
    public Adm getAdmOrFirstValidParentIfNotFound(final String countryCode, final String adm1Code,
            final String adm2Code, final String adm3Code, final String adm4Code) {
        Assert.notNull(countryCode);
        Adm adm = null;
        String adm1CodeTemp = adm1Code;
        String adm2CodeTemp = adm2Code;
        String adm3CodeTemp = adm3Code;
        String adm4CodeTemp = adm4Code;
        do {
            adm = getAdm(countryCode, adm1CodeTemp, adm2CodeTemp, adm3CodeTemp, adm4CodeTemp);
            if (adm == null) {
                // downgrade the admvalue to search a lower level
                if (adm4CodeTemp != null) {
                    adm4CodeTemp = null;
                    continue;
                } else if (adm3CodeTemp != null) {
                    adm3CodeTemp = null;
                    continue;
                } else if (adm2CodeTemp != null) {
                    adm2CodeTemp = null;
                    continue;
                } else {
                    return getAdm1(countryCode, adm1Code);
                }
            } else {
                return adm;
            }
        } while (adm == null);
        return adm;
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.gisgraphy.domain.repository.IAdmDao#suggestMostAccurateAdm(java.lang.String,
     *      java.lang.String, java.lang.String, java.lang.String,
     *      java.lang.String, com.gisgraphy.domain.geoloc.entity.GisFeature)
     */
    public Adm suggestMostAccurateAdm(String countryCode, String adm1Code, String adm2Code, String adm3Code,
            String adm4Code, GisFeature gisfeature) {
        Assert.notNull(countryCode);
        logger.debug("try to find ADM for " + adm1Code + "." + adm2Code + "." + adm3Code + "." + adm4Code);
        Adm adm = getAdm(countryCode.toUpperCase(), adm1Code, adm2Code, adm3Code, adm4Code);
        if (adm == null) {
            // must get the most accurate adm
            String lowestNotNullAdmCode = getLowestNotNullAdmCode(adm1Code, adm2Code, adm3Code, adm4Code);
            int level = Adm.getProcessedLevelFromCodes(adm1Code, adm2Code, adm3Code, adm4Code);

            if (lowestNotNullAdmCode != null && level != 0) {
                List<Adm> levelAdms = getAdmByCountryAndCodeAndLevel(countryCode.toUpperCase(),
                        lowestNotNullAdmCode, level);
                Adm levelAdm = null;
                if (levelAdms.size() == 1) {
                    levelAdm = levelAdms.get(0);
                }
                Adm nearestParentAdm = getAdmOrFirstValidParentIfNotFound(countryCode.toUpperCase(), adm1Code,
                        adm2Code, adm3Code, adm4Code);
                if (levelAdm != null) {
                    if (nearestParentAdm != null) {
                        if (((level - nearestParentAdm.getLevel()) <= 2)) {
                            // the admcode of the lowestlevel is probably not
                            // well set, return the specified level Adm
                            logger.warn("[wrong adm" + (level - 1) + "code] : The adm" + (level - 1) + "Code for "
                                    + gisfeature + "[" + adm1Code + "." + adm2Code + "." + adm3Code + "." + adm4Code
                                    + "] is wrong. Please correct it to " + levelAdm);
                            return levelAdm;
                        } else {
                            logger.warn("[wrong adm codes] : " + ((level - nearestParentAdm.getLevel()) - 1)
                                    + " admCodes are wrong for " + gisfeature + "[" + adm1Code + "." + adm2Code
                                    + "." + adm3Code + "." + adm4Code + "] but the adm" + level
                                    + "code is corect. The suggested Adm is " + nearestParentAdm);
                            return nearestParentAdm;
                        }

                    } else {
                        logger.error("[Wrong adm codes] an Adm" + level + " exists but no parent for " + adm1Code
                                + "." + adm2Code + "." + adm3Code + "." + adm4Code + " : all the code before adm"
                                + level + " are wrong");
                        return levelAdm;
                    }
                } else {
                    // there is no adm with this code for this level, we return
                    // the nearest parent
                    // split logs
                    if ((nearestParentAdm != null) && ((level - nearestParentAdm.getLevel()) == 1)) {
                        logger.warn("[wrong adm" + level + "Code] The adm" + (level) + "Code for " + gisfeature
                                + "[" + adm1Code + "." + adm2Code + "." + adm3Code + "." + adm4Code
                                + "] is not well set. The nearest parent found is " + nearestParentAdm);
                    } else {
                        logger.warn("[wrong adm codes] The adm" + (level) + "Code for " + gisfeature + "["
                                + adm1Code + "." + adm2Code + "." + adm3Code + "." + adm4Code
                                + "] is not well set and some others. The nearest parent found is "
                                + nearestParentAdm);
                    }
                    return nearestParentAdm;

                }
            } else {
                // The specified adm code doesn't allow a search
                logger.warn("No adm can be found for [" + adm1Code + "." + adm2Code + "." + adm3Code + "."
                        + adm4Code + "]");
                return null;
            }
        } else {
            return adm;
        }
    }

    public int deleteAllByLevel(final int level) {
        return ((Integer) this.getHibernateTemplate().execute(new HibernateCallback() {

            public Object doInHibernate(Session session) throws PersistenceException {
                String queryString = "delete from " + persistentClass.getSimpleName() + " as a where a.level=?";

                Query qry = session.createQuery(queryString);
                qry.setParameter(0, level);
                qry.setCacheable(false);

                return Integer.valueOf(qry.executeUpdate());

            }
        })).intValue();
    }

    private String getLowestNotNullAdmCode(String adm1Code, String adm2Code, String adm3Code, String adm4Code) {
        if (!isAdmCodeEmpty(adm1Code)) {
            if (!isAdmCodeEmpty(adm2Code)) {
                if (!isAdmCodeEmpty(adm3Code)) {
                    if (!isAdmCodeEmpty(adm4Code)) {
                        // adm1,adm2,adm3,adm4
                        return adm4Code;
                    } else {
                        // adm1,adm2,adm3,null
                        return adm3Code;
                    }
                } else {
                    // adm1,Adm2, null..
                    return adm2Code;
                }
            } else {
                // adm1,null...
                return adm1Code;
            }
        } else {
            // if adm1 is empty can not retrieve any Adm
            return null;
        }
    }

    @SuppressWarnings("unchecked")
    public List<Long> listFeatureIdByLevel(final int level) {
        return ((List<Long>) this.getHibernateTemplate().execute(new HibernateCallback() {

            public Object doInHibernate(final Session session) throws PersistenceException {
                final String queryString = "select featureId from " + persistentClass.getSimpleName()
                        + " as a where a.level=?";

                final Query qry = session.createQuery(queryString);
                qry.setParameter(0, level);
                qry.setCacheable(false);
                return qry.list();

            }
        }));
    }

}