Java tutorial
/******************************************************************************* * 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 static com.gisgraphy.hibernate.projection.SpatialProjection.DISTANCE_SPHERE_FUNCTION; import java.util.ArrayList; import java.util.List; import javax.persistence.PersistenceException; import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.NotImplementedException; import org.hibernate.Criteria; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.criterion.ProjectionList; import org.hibernate.criterion.Restrictions; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.orm.hibernate3.HibernateCallback; import org.springframework.stereotype.Repository; import org.springframework.util.Assert; import com.gisgraphy.GisgraphyException; import com.gisgraphy.domain.geoloc.entity.GisFeature; import com.gisgraphy.domain.geoloc.entity.OpenStreetMap; import com.gisgraphy.domain.geoloc.entity.Street; import com.gisgraphy.domain.geoloc.entity.event.EventManager; import com.gisgraphy.domain.geoloc.entity.event.GisFeatureDeletedEvent; import com.gisgraphy.domain.geoloc.entity.event.GisFeatureStoredEvent; import com.gisgraphy.domain.geoloc.entity.event.PlaceTypeDeleteAllEvent; import com.gisgraphy.domain.valueobject.GisgraphyConfig; import com.gisgraphy.domain.valueobject.SRID; import com.gisgraphy.domain.valueobject.StreetDistance; import com.gisgraphy.helper.GeolocHelper; import com.gisgraphy.helper.IntrospectionHelper; import com.gisgraphy.hibernate.criterion.DistanceRestriction; import com.gisgraphy.hibernate.criterion.FulltextRestriction; import com.gisgraphy.hibernate.criterion.IntersectsRestriction; import com.gisgraphy.hibernate.criterion.NativeSQLOrder; import com.gisgraphy.hibernate.criterion.ProjectionOrder; import com.gisgraphy.hibernate.criterion.ResultTransformerUtil; import com.gisgraphy.hibernate.projection.ProjectionBean; import com.gisgraphy.hibernate.projection.SpatialProjection; import com.gisgraphy.street.IStreetFactory; import com.gisgraphy.street.StreetFactory; import com.gisgraphy.street.StreetSearchMode; import com.gisgraphy.street.StreetType; import com.vividsolutions.jts.geom.Point; import com.vividsolutions.jts.geom.Polygon; /** * A data access object for {@link OpenStreetMap} Object * * @author <a href="mailto:david.masclet@gisgraphy.com">David Masclet</a> */ @Repository public class OpenStreetMapDao extends GenericDao<OpenStreetMap, Long> implements IOpenStreetMapDao { private IStreetFactory streetFactory = new StreetFactory(); private EventManager eventManager; /** * The logger */ protected static final Logger logger = LoggerFactory.getLogger(OpenStreetMapDao.class); protected static final int DEFAULT_DISTANCE = 500; /** * Default constructor */ public OpenStreetMapDao() { super(OpenStreetMap.class); } /* (non-Javadoc) * @see com.gisgraphy.domain.repository.IOpenStreetMapDao#getNearestAndDistanceFrom(com.vividsolutions.jts.geom.Point, double, int, int, java.lang.String, java.lang.String) */ @SuppressWarnings("unchecked") public List<StreetDistance> getNearestAndDistanceFrom(final Point point, final double distance, final int firstResult, final int maxResults, final StreetType streetType, final Boolean oneWay, final String name, final StreetSearchMode streetSearchMode, final boolean includeDistanceField) { if (streetSearchMode == StreetSearchMode.FULLTEXT && !GisgraphyConfig.STREET_SEARCH_FULLTEXT_MODE) { throw new GisgraphyException( "The fulltext mode has been removed in gisgraphy v 3.0 and has been replaced by fulltext webservice with placetype=street. please Consult user guide."); } if (name != null && streetSearchMode == null) { throw new IllegalArgumentException("streetSearchmode can not be null if name is provided"); } if (point == null && streetSearchMode == StreetSearchMode.CONTAINS) { throw new IllegalArgumentException( "you must specify lat/lng when streetsearchmode = " + StreetSearchMode.CONTAINS); } return (List<StreetDistance>) this.getHibernateTemplate().execute(new HibernateCallback() { public Object doInHibernate(Session session) throws PersistenceException { Criteria criteria = session.createCriteria(OpenStreetMap.class); List<String> fieldList = IntrospectionHelper.getFieldsAsList(OpenStreetMap.class); ProjectionList projections = ProjectionBean.fieldList(fieldList, false); if (includeDistanceField && point != null) { projections.add( // SpatialProjection.distance_sphere(point, GisFeature.LOCATION_COLUMN_NAME).as( // "distance")); SpatialProjection.distance_pointToLine(point, OpenStreetMap.SHAPE_COLUMN_NAME) .as("distance")); } criteria.setProjection(projections); if (includeDistanceField && point != null) { criteria.addOrder(new ProjectionOrder("distance")); } if (maxResults > 0) { criteria = criteria.setMaxResults(maxResults); } if (firstResult >= 1) { criteria = criteria.setFirstResult(firstResult - 1); } if (point != null) { Polygon polygonBox = GeolocHelper.createPolygonBox(point.getX(), point.getY(), distance); criteria = criteria.add(new IntersectsRestriction(OpenStreetMap.SHAPE_COLUMN_NAME, polygonBox)); } if (name != null) { if (streetSearchMode == StreetSearchMode.CONTAINS) { criteria = criteria.add(Restrictions.isNotNull("name"));//optimisation! criteria = criteria.add( Restrictions.ilike(OpenStreetMap.FULLTEXTSEARCH_PROPERTY_NAME, "%" + name + "%")); //criteria = criteria.add(new PartialWordSearchRestriction(OpenStreetMap.PARTIALSEARCH_VECTOR_COLUMN_NAME, name)); } else if (streetSearchMode == StreetSearchMode.FULLTEXT) { criteria = criteria.add( new FulltextRestriction(OpenStreetMap.FULLTEXTSEARCH_VECTOR_PROPERTY_NAME, name)); } else { throw new NotImplementedException( streetSearchMode + " is not implemented for street search"); } } if (streetType != null) { criteria = criteria.add(Restrictions.eq("streetType", streetType)); } if (oneWay != null) { criteria = criteria.add(Restrictions.eq("oneWay", oneWay)); } criteria.setCacheable(true); // List<Object[]> queryResults =testCriteria.list(); List<?> queryResults = criteria.list(); if (queryResults != null && queryResults.size() != 0) { String[] propertiesNameArray; if (includeDistanceField && point != null) { propertiesNameArray = (String[]) ArrayUtils .add(IntrospectionHelper.getFieldsAsArray(OpenStreetMap.class), "distance"); } else { propertiesNameArray = IntrospectionHelper.getFieldsAsArray(OpenStreetMap.class); } List<StreetDistance> results = ResultTransformerUtil .transformToStreetDistance(propertiesNameArray, queryResults); return results; } else { return new ArrayList<StreetDistance>(); } } }); } /* (non-Javadoc) * @see com.gisgraphy.domain.repository.IOpenStreetMapDao#getByGid(java.lang.Long) */ public OpenStreetMap getByGid(final Long gid) { Assert.notNull(gid); return (OpenStreetMap) this.getHibernateTemplate().execute(new HibernateCallback() { public Object doInHibernate(Session session) throws PersistenceException { String queryString = "from " + OpenStreetMap.class.getSimpleName() + " as c where c.gid= ?"; Query qry = session.createQuery(queryString); qry.setCacheable(true); qry.setParameter(0, gid); OpenStreetMap result = (OpenStreetMap) qry.uniqueResult(); return result; } }); } /* (non-Javadoc) * @see com.gisgraphy.domain.repository.IOpenStreetMapDao#buildIndexForStreetNameSearch() */ public Integer updateTS_vectorColumnForStreetNameSearch() { return (Integer) this.getHibernateTemplate().execute(new HibernateCallback() { public Object doInHibernate(Session session) throws PersistenceException { session.flush(); logger.info("will update " + OpenStreetMap.FULLTEXTSEARCH_VECTOR_PROPERTY_NAME.toLowerCase() + " field"); String updateFulltextField = "UPDATE openStreetMap SET " + OpenStreetMap.FULLTEXTSEARCH_VECTOR_PROPERTY_NAME.toLowerCase() + " = to_tsvector('simple',coalesce(" + OpenStreetMap.FULLTEXTSEARCH_COLUMN_NAME + ",'')) where name is not null"; Query qryUpdateFulltextField = session.createSQLQuery(updateFulltextField); int numberOfLineUpdatedForFulltext = qryUpdateFulltextField.executeUpdate(); int numberOfLineUpdatedForPartial = 0; return Integer.valueOf(numberOfLineUpdatedForFulltext + numberOfLineUpdatedForPartial); } }); } /* (non-Javadoc) * @see com.gisgraphy.domain.repository.IOpenStreetMapDao#buildIndexForStreetNameSearch() */ public Integer updateTS_vectorColumnForStreetNameSearchPaginate(final long from, final long to) { return (Integer) this.getHibernateTemplate().execute(new HibernateCallback() { public Object doInHibernate(Session session) throws PersistenceException { session.flush(); logger.info("will update " + OpenStreetMap.FULLTEXTSEARCH_VECTOR_PROPERTY_NAME.toLowerCase() + " field"); String updateFulltextField = "UPDATE openStreetMap SET " + OpenStreetMap.FULLTEXTSEARCH_VECTOR_PROPERTY_NAME.toLowerCase() + " = to_tsvector('simple',coalesce(" + OpenStreetMap.FULLTEXTSEARCH_COLUMN_NAME + ",'')) where gid >= " + from + " and gid <= " + to + " and name is not null"; Query qryUpdateFulltextField = session.createSQLQuery(updateFulltextField); int numberOfLineUpdatedForFulltext = qryUpdateFulltextField.executeUpdate(); int numberOfLineUpdatedForPartial = 0; return Integer.valueOf(numberOfLineUpdatedForFulltext + numberOfLineUpdatedForPartial); } }); } /* (non-Javadoc) * @see com.gisgraphy.domain.repository.IOpenStreetMapDao#createGISTIndex() */ public void createSpatialIndexes() { this.getHibernateTemplate().execute(new HibernateCallback() { public Object doInHibernate(Session session) throws PersistenceException { session.flush(); String locationIndexName = OpenStreetMap.LOCATION_COLUMN_NAME.toLowerCase() + "indexopenstreetmap"; logger.info("checking if " + locationIndexName + " exists"); String checkingLocationIndex = "SELECT 1 FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace WHERE c.relname = '" + locationIndexName + "'"; Query checkingLocationIndexQuery = session.createSQLQuery(checkingLocationIndex); Object locationIndexExists = checkingLocationIndexQuery.uniqueResult(); if (locationIndexExists != null) { logger.info( "will create GIST index for the " + OpenStreetMap.LOCATION_COLUMN_NAME + " column"); String createIndexForLocation = "CREATE INDEX " + locationIndexName + " ON openstreetmap USING GIST (" + OpenStreetMap.LOCATION_COLUMN_NAME.toLowerCase() + ")"; Query qryUpdateLocationIndex = session.createSQLQuery(createIndexForLocation); qryUpdateLocationIndex.executeUpdate(); } else { logger.info("won't create GIST index for the " + OpenStreetMap.LOCATION_COLUMN_NAME + " column because it already exists"); } String shapeIndexName = OpenStreetMap.SHAPE_COLUMN_NAME.toLowerCase() + "indexopenstreetmap"; logger.info("checking if " + shapeIndexName + " exists"); String checkingShapeIndex = "SELECT 1 FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace WHERE c.relname = '" + shapeIndexName + "'"; Query checkingShapeIndexQuery = session.createSQLQuery(checkingShapeIndex); Object shapeIndexExists = checkingShapeIndexQuery.uniqueResult(); if (shapeIndexExists != null) { logger.info("will create GIST index for the " + OpenStreetMap.SHAPE_COLUMN_NAME + " column"); String createIndexForShape = "CREATE INDEX " + OpenStreetMap.SHAPE_COLUMN_NAME.toLowerCase() + "indexopenstreetmap ON openstreetmap USING GIST (" + OpenStreetMap.SHAPE_COLUMN_NAME.toLowerCase() + ")"; Query qryUpdateShapeIndex = session.createSQLQuery(createIndexForShape); qryUpdateShapeIndex.executeUpdate(); } else { logger.info("won't create GIST index for the " + OpenStreetMap.SHAPE_COLUMN_NAME + " column because it already exists"); } return null; } }); } /* (non-Javadoc) * @see com.gisgraphy.domain.repository.IOpenStreetMapDao#createGISTIndex() */ public void createFulltextIndexes() { this.getHibernateTemplate().execute(new HibernateCallback() { public Object doInHibernate(Session session) throws PersistenceException { session.flush(); logger.info("will create Fulltext index"); String createFulltextIndex = "CREATE INDEX " + OpenStreetMap.FULLTEXTSEARCH_VECTOR_PROPERTY_NAME.toLowerCase() + "indexopenstreetmap ON openstreetmap USING gin(" + OpenStreetMap.FULLTEXTSEARCH_VECTOR_PROPERTY_NAME.toLowerCase() + ")"; Query fulltextIndexQuery = session.createSQLQuery(createFulltextIndex); fulltextIndexQuery.executeUpdate(); return null; } }); } /* (non-Javadoc) * @see com.gisgraphy.domain.repository.IOpenStreetMapDao#countEstimate() */ public long countEstimate() { return (Long) this.getHibernateTemplate().execute(new HibernateCallback() { public Object doInHibernate(Session session) throws PersistenceException { String queryString = "select max(gid)-min(gid)+1 from " + persistentClass.getSimpleName(); Query qry = session.createQuery(queryString); qry.setCacheable(true); Long count = (Long) qry.uniqueResult(); return count == null ? 0 : count; } }); } @Override public OpenStreetMap save(OpenStreetMap openStreetMap) { OpenStreetMap savedEntity = super.save(openStreetMap); Street street = streetFactory.create(savedEntity); GisFeatureStoredEvent CreatedEvent = new GisFeatureStoredEvent(street); eventManager.handleEvent(CreatedEvent); return savedEntity; } /* * (non-Javadoc) * * @see com.gisgraphy.domain.repository.GenericDao#remove(java.lang.Object) */ @Override public void remove(OpenStreetMap openStreetMap) { super.remove(openStreetMap); Street street = streetFactory.create(openStreetMap); GisFeatureDeletedEvent gisFeatureDeletedEvent = new GisFeatureDeletedEvent(street); eventManager.handleEvent(gisFeatureDeletedEvent); } /* * (non-Javadoc) * * @see com.gisgraphy.domain.repository.GenericDao#deleteAll() */ @Override public int deleteAll() { int numberOfOpenStreetMapDeleted = super.deleteAll(); PlaceTypeDeleteAllEvent placeTypeDeleteAllEvent = new PlaceTypeDeleteAllEvent(Street.class); eventManager.handleEvent(placeTypeDeleteAllEvent); return numberOfOpenStreetMapDeleted; } public OpenStreetMap getByOpenStreetMapId(final Long openstreetmapId) { Assert.notNull(openstreetmapId); return (OpenStreetMap) this.getHibernateTemplate().execute(new HibernateCallback() { public Object doInHibernate(Session session) throws PersistenceException { String queryString = "from " + OpenStreetMap.class.getSimpleName() + " as c where c.openstreetmapId= ?"; Query qry = session.createQuery(queryString); qry.setMaxResults(1); //we need to limit to 1 because a street can be in two countries qry.setCacheable(true); qry.setParameter(0, openstreetmapId); OpenStreetMap result = (OpenStreetMap) qry.uniqueResult(); return result; } }); } /* (non-Javadoc) * @see com.gisgraphy.domain.repository.IOpenStreetMapDao#getMaxOpenstreetMapId() */ public long getMaxOpenstreetMapId() { return (Long) this.getHibernateTemplate().execute(new HibernateCallback() { public Object doInHibernate(Session session) throws PersistenceException { String queryString = "select max(openstreetmapId) from " + OpenStreetMap.class.getSimpleName(); Query qry = session.createQuery(queryString); qry.setCacheable(true); Long count = (Long) qry.uniqueResult(); return count == null ? 0 : count; } }); } @SuppressWarnings({ "unchecked", "rawtypes" }) public OpenStreetMap getNearestByosmIds(final Point point, final List<Long> ids) { if (ids == null || ids.size() == 0) { return null; } return (OpenStreetMap) this.getHibernateTemplate().execute(new HibernateCallback() { public Object doInHibernate(Session session) throws PersistenceException { Criteria criteria = session.createCriteria(OpenStreetMap.class); criteria.add(new DistanceRestriction(point, DEFAULT_DISTANCE, true)); criteria.add(Restrictions.in("openstreetmapId", ids)); String pointAsString = "ST_GeometryFromText('POINT(" + point.getX() + " " + point.getY() + ")'," + SRID.WGS84_SRID.getSRID() + ")"; String distanceCondition = new StringBuffer().append(DISTANCE_SPHERE_FUNCTION).append("(") .append(pointAsString).append(",").append(SpatialProjection.ST_CLOSEST_POINT).append("(") .append("this_.").append(OpenStreetMap.SHAPE_COLUMN_NAME).append(",").append(pointAsString) .append(")").append(")").toString(); criteria.addOrder(new NativeSQLOrder(distanceCondition)); criteria = criteria.setMaxResults(1); criteria.setCacheable(true); // List<Object[]> queryResults =testCriteria.list(); OpenStreetMap openStreetMap = (OpenStreetMap) criteria.uniqueResult(); return openStreetMap; } }); } /* (non-Javadoc) * @see com.gisgraphy.domain.repository.IOpenStreetMapDao#getMaxOpenstreetMapId() */ public long getMaxGid() { return (Long) this.getHibernateTemplate().execute(new HibernateCallback() { public Object doInHibernate(Session session) throws PersistenceException { String queryString = "select max(gid) from " + OpenStreetMap.class.getSimpleName(); Query qry = session.createQuery(queryString); qry.setCacheable(true); Long count = (Long) qry.uniqueResult(); return count == null ? 0 : count; } }); } @Autowired public void setEventManager(EventManager eventManager) { this.eventManager = eventManager; } public void setStreetFactory(IStreetFactory streetFactory) { this.streetFactory = streetFactory; } public OpenStreetMap getNearestRoadFrom(final Point point) { return getNearestFrom(point, true, true); } public OpenStreetMap getNearestFrom(final Point point) { return getNearestFrom(point, false, true); } @SuppressWarnings({ "unchecked", "rawtypes" }) public OpenStreetMap getNearestFrom(final Point point, final boolean onlyroad, final boolean filterEmptyName) { if (point == null) { return null; } return (OpenStreetMap) this.getHibernateTemplate().execute(new HibernateCallback() { public Object doInHibernate(Session session) throws PersistenceException { Criteria criteria = session.createCriteria(OpenStreetMap.class); if (point != null) { //An intersect restriction will probably have better performances and use the index than a distance restriction Polygon polygonBox = GeolocHelper.createPolygonBox(point.getX(), point.getY(), DEFAULT_DISTANCE); criteria = criteria.add(new IntersectsRestriction(OpenStreetMap.SHAPE_COLUMN_NAME, polygonBox)); } if (onlyroad) { criteria = criteria.add(Restrictions.ne("streetType", StreetType.FOOTWAY)); } if (filterEmptyName) { criteria = criteria.add(Restrictions.isNotNull("name")); } String pointAsString = "ST_GeometryFromText('POINT(" + point.getX() + " " + point.getY() + ")'," + SRID.WGS84_SRID.getSRID() + ")"; String distanceCondition = new StringBuffer().append(DISTANCE_SPHERE_FUNCTION).append("(") .append(pointAsString).append(",").append(SpatialProjection.ST_CLOSEST_POINT).append("(") .append("this_.").append(OpenStreetMap.SHAPE_COLUMN_NAME).append(",").append(pointAsString) .append(")").append(")").toString(); criteria.addOrder(new NativeSQLOrder(distanceCondition)); criteria = criteria.setMaxResults(1); criteria.setCacheable(true); // List<Object[]> queryResults =testCriteria.list(); OpenStreetMap openStreetMap = (OpenStreetMap) criteria.uniqueResult(); return openStreetMap; } }); } public String getShapeAsWKTByGId(final Long gid) { if (gid == null) { return null; } return (String) this.getHibernateTemplate().execute(new HibernateCallback() { public Object doInHibernate(Session session) throws PersistenceException { String queryString = "select ST_AsText(" + GisFeature.SHAPE_COLUMN_NAME + ") from " + persistentClass.getSimpleName() + " as o where o.gid=?"; Query qry = session.createQuery(queryString); qry.setParameter(0, gid); qry.setCacheable(true); return (String) qry.uniqueResult(); } }); } }