Java tutorial
/** * Copyright 2011 Jason Ferguson. * <p/> * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * <p/> * http://www.apache.org/licenses/LICENSE-2.0 * <p/> * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package org.jason.mapmaker.server.service; import com.vividsolutions.jts.geom.*; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.geotools.geometry.jts.JTSFactoryFinder; import org.jason.mapmaker.server.repository.FeatureRepository; import org.jason.mapmaker.server.util.ZipUtil; import org.jason.mapmaker.shared.exceptions.RepositoryException; import org.jason.mapmaker.shared.exceptions.ServiceException; import org.jason.mapmaker.shared.model.BorderPoint; import org.jason.mapmaker.shared.model.Feature; import org.jason.mapmaker.shared.model.FeaturesMetadata; import org.jason.mapmaker.shared.model.Location; import org.jason.mapmaker.shared.util.FeatureUtil; import org.jason.mapmaker.shared.util.GeographyUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.*; import static org.apache.commons.lang.StringUtils.split; /** * Implementation of FeaturesService interface * * @author Jason Ferguson * @since 0.3 */ @Service("featureService") public class FeatureServiceImpl implements FeatureService { private static Logger log = LoggerFactory.getLogger(FeatureServiceImpl.class); private FeaturesMetadataService featuresMetadataService; private FeatureRepository featureRepository; @Autowired public void setFeaturesMetadataService(FeaturesMetadataService featuresMetadataService) { this.featuresMetadataService = featuresMetadataService; } @Autowired public void setFeatureRepository(FeatureRepository featureRepository) { this.featureRepository = featureRepository; } @Override public void persist(Feature object) throws ServiceException { try { featureRepository.save(object); } catch (Exception e) { log.debug("persist() threw RepositoryException: ", e); throw new ServiceException(e); } } @Override public void remove(Feature object) throws ServiceException { try { featureRepository.delete(object); } catch (Exception e) { log.debug("remove() threw RepositoryException: ", e); throw new ServiceException(e); } } @Override public void saveList(List<Feature> featureList) throws ServiceException { try { featureRepository.saveList(featureList); } catch (Exception ex) { log.debug("saveList() threw ServiceException", ex); throw new ServiceException(ex); } } @Override public List<String> getFeatureClasses() { return featureRepository.getAvailableFeatureClasses(); } @Override public List<Feature> getFeatures(Location location, String featureClassName) { // get everything of the given feature class within the general bounding box of the location List<Feature> initialList = featureRepository.getFeaturesByBoxAndFeatureClassName(location.getBoundingBox(), featureClassName); if (initialList.size() == 0) { return initialList; } // create a polygon of the border points int numBorderPoints = location.getBorderPointList().size(); Coordinate[] coordinates = new Coordinate[numBorderPoints + 1]; for (int i = 0; i < numBorderPoints; i++) { BorderPoint bp = location.getBorderPointList().get(i); coordinates[i] = new Coordinate(bp.getLng(), bp.getLat()); } // close the polygon coordinates[numBorderPoints] = coordinates[0]; GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory(null); // create the linear ring of the outer border. However, the outer border is the only border, so pass null // for the second argument of createPolygon() LinearRing lr = geometryFactory.createLinearRing(coordinates); Polygon polygon = geometryFactory.createPolygon(lr, null); // check if point is in Polygon, if not throw it out of the feature list List<Feature> filteredList = new ArrayList<Feature>(); for (Feature f : initialList) { // we can only check if a given Geometry is inside a polygon, so create a Point from the coordinates Point point = geometryFactory.createPoint(new Coordinate(f.getLng(), f.getLat())); if (polygon.contains(point)) { filteredList.add(f); } } return filteredList; } public void deleteByFeaturesMetadata(FeaturesMetadata fm) throws ServiceException { String validatedGeoId = StringUtils.left(fm.getStateGeoId(), 2); try { featureRepository.deleteByStateGeoId(validatedGeoId); } catch (RepositoryException e) { throw new ServiceException(e); } fm.setCurrentStatus(GeographyUtils.Status.NOT_IMPORTED); featuresMetadataService.update(fm); } @Override public void importFromFeaturesMetadata(FeaturesMetadata fm) throws ServiceException { String url = generateUrl(fm.getStateGeoId(), fm.getUsgsDate()); importFromUrl(url, fm); fm.setCurrentStatus(GeographyUtils.Status.IMPORTED); featuresMetadataService.update(fm); } @Override public String generateUrl(String geoId, String dateUpdated) { String abbreviation = GeographyUtils.getAbbreviationForState(GeographyUtils.getStateForGeoId(geoId)); String result = "http://geonames.usgs.gov/docs/stategaz/" + abbreviation + "_Features_" + dateUpdated + ".zip"; return result; } @Override public void importFromUrl(String url, FeaturesMetadata fm) throws ServiceException { URL u; try { u = new URL(url); } catch (MalformedURLException ex) { log.debug("Exception thrown:", ex.getMessage()); throw new ServiceException(ex); } List<File> fileList; try { fileList = ZipUtil.decompress(u); } catch (Exception e) { log.debug("Exception thrown:", e.getMessage()); throw new ServiceException(e); } if (fileList == null || fileList.size() == 0) { log.debug("File list is null or zero!"); throw new ServiceException("File List contains no files!"); } File file = fileList.get(0); // get the txt file handler try { BufferedReader reader = new BufferedReader(new FileReader(file)); reader.readLine(); // ignore header line String line = reader.readLine(); List<Feature> featureList = new ArrayList<Feature>(); // arraylist may not be the best choice since I don't know how many features I'm importing int counter = 1; while (line != null) { String[] splitLine = split(line, "|"); // static import of StringUtils because I don't like regex's if (!NumberUtils.isNumber(splitLine[0]) || !NumberUtils.isNumber(splitLine[9]) || !NumberUtils.isNumber(splitLine[10])) { System.out.println("Feature ID#" + splitLine[0] + " fails isNumeric() test. Skipping."); line = reader.readLine(); continue; // "silently" die } // only import the manmade features if (FeatureUtil.isManmadeFeature(splitLine[2])) { // setting this to variables and using the non-default Feature constructor means this is // easier to debug. Yay. // sometimes the USGS state file isn't limited to a single state... god only knows what the problem is String stateGeoId = splitLine[4]; if (fm.getStateGeoId().equals(stateGeoId)) { int id = Integer.parseInt(splitLine[0]); String featureName = StringUtils.left(splitLine[1], 99); String featureClass = StringUtils.left(splitLine[2], 99); double lat = Double.parseDouble(splitLine[9]); double lng = Double.parseDouble(splitLine[10]); Feature feature = new Feature(id, featureName, featureClass, lat, lng, fm); feature.setFeatureSource("usgs"); featureList.add(feature); counter++; } } if (counter % 100000 == 0) { System.out.println("Processed " + counter + " items"); try { saveList(featureList); featureList.clear(); } catch (ServiceException e) { log.debug("Exception thrown: ", e.getMessage()); break; } } line = reader.readLine(); } saveList(featureList); reader.close(); } catch (IOException e) { log.debug("Exception thrown:", e); throw new ServiceException(e); } file.delete(); } @Override public void update(Feature obj) { featureRepository.update(obj); } @Override public void deleteAll() { featureRepository.deleteAll(); } }