org.alex73.osm.monitors.export.ReadChangesets.java Source code

Java tutorial

Introduction

Here is the source code for org.alex73.osm.monitors.export.ReadChangesets.java

Source

/**************************************************************************
     
Some tools for OSM.
    
 Copyright (C) 2013 Ale Buoj?yk <alex73mail@gmail.com>
           Home page: http://www.omegat.org/
           Support center: http://groups.yahoo.com/group/OmegaT/
    
 This is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.
    
 This software 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 General Public License for more details.
    
 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 **************************************************************************/

package org.alex73.osm.monitors.export;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;

import javax.xml.bind.JAXBContext;

import org.alex73.osm.utils.Belarus;
import org.alex73.osm.utils.Env;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;

import osm.xmldatatypes.Changeset;
import osm.xmldatatypes.Osm;
import osm.xmldatatypes.OsmChange;

/**
 *  ?   http://planet.openstreetmap.org/replication/changesets/   ?  
 * ?   2 .
 */
public class ReadChangesets {
    static JAXBContext CONTEXT;

    /**
     * ? changeset'  before  after.  after==null, ? ? ? ?? before.
     */
    public static List<Changeset> retrieve(Set<Long> knownChangesetsBefore, Set<Long> knownChangesetsAfter)
            throws Exception {
        System.out.println("Retrieve changesets");
        CONTEXT = JAXBContext.newInstance(OsmChange.class, Osm.class);

        List<Changeset> forProcess = new ArrayList<>();

        read: for (long i = readLast(); i >= 0; i--) {
            List<Changeset> changesets = readSeq(i);

            changesets.removeIf(ch -> ch.getClosedAt() == null); // ? ?? ?

            if (changesets.isEmpty()) {
                continue;
            }

            // changesets from latest to previous
            sort(changesets);
            Collections.reverse(changesets);

            boolean beforeAfter = knownChangesetsAfter == null;
            for (Changeset ch : changesets) {
                if (!beforeAfter && knownChangesetsAfter.contains(ch.getId())) {
                    //  changeset ?  after, ?   ? - 
                    beforeAfter = true;
                }
                if (knownChangesetsBefore.contains(ch.getId())) {
                    //  changeset ?  before,  ??  
                    break read;
                }
                if (beforeAfter && !isOutside(ch)) {
                    forProcess.add(ch);
                }
            }
        }

        sort(forProcess);
        return forProcess;
    }

    public static void sort(List<Changeset> changesets) {
        Collections.sort(changesets, new Comparator<Changeset>() {
            @Override
            public int compare(Changeset o1, Changeset o2) {
                long t1 = o1.getClosedAt().toGregorianCalendar().getTimeInMillis();
                long t2 = o2.getClosedAt().toGregorianCalendar().getTimeInMillis();
                return Long.compare(t1, t2);
            }
        });
    }

    /**
     *  changeset  ID.
     */
    public static byte[] download(Changeset ch) throws Exception {
        File cache = new File(Env.readProperty("data.cache") + "/changesets/" + ch.getId() + ".xml");
        byte[] xml;
        if (cache.exists()) {
            xml = FileUtils.readFileToByteArray(cache);
        } else {
            xml = get("http://www.openstreetmap.org/api/0.6/changeset/" + ch.getId() + "/download");
            cache.getParentFile().mkdirs();
            FileUtils.writeByteArrayToFile(cache, xml);
        }
        return xml;
    }

    static Pattern RE_YAML = Pattern.compile("sequence: ([0-9]+)");

    /**
     *   ? .
     */
    static long readLast() throws Exception {
        byte[] yaml = get("http://planet.openstreetmap.org/replication/changesets/state.yaml");
        BufferedReader rd = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(yaml)));

        Long result = null;
        String s;
        while ((s = rd.readLine()) != null) {
            Matcher m = RE_YAML.matcher(s);
            if (m.matches()) {
                result = Long.parseLong(m.group(1));
            }
        }
        if (result == null) {
            throw new Exception("No sequence");
        }
        return result;
    }

    /**
     *  osm  ?? changeset'.
     */
    static List<Changeset> readSeq(long index) throws Exception {
        String s = new DecimalFormat("000000000").format(index);
        File cache = new File(Env.readProperty("data.cache") + "/changesets/" + s + ".osm.gz");
        byte[] xml;
        if (cache.exists()) {
            System.out.println("Read from cache " + cache);
            xml = FileUtils.readFileToByteArray(cache);
        } else {
            xml = get("http://planet.openstreetmap.org/replication/changesets/" + s.substring(0, 3) + "/"
                    + s.substring(3, 6) + "/" + s.substring(6) + ".osm.gz");
            cache.getParentFile().mkdirs();
            FileUtils.writeByteArrayToFile(cache, xml);
        }
        if (xml.length == 0) {
            return new ArrayList<>();
        }
        Osm result = (Osm) CONTEXT.createUnmarshaller()
                .unmarshal(new GZIPInputStream(new ByteArrayInputStream(xml)));
        return result.getChangeset();
    }

    /**
     *  -  ? ?
     */
    static boolean isOutside(Changeset ch) {
        if (ch.getMinLat() > Belarus.MAX_LAT || ch.getMaxLat() < Belarus.MIN_LAT || ch.getMinLon() > Belarus.MAX_LON
                || ch.getMaxLon() < Belarus.MIN_LON) {
            return true;
        }
        return false;
    }

    /**
     *  URL.
     */
    static byte[] get(String url) throws Exception {
        System.out.println("Load " + url);
        HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
        if (conn.getResponseCode() != 200) {
            throw new IOException("Call " + url + ": " + conn.getResponseCode() + " " + conn.getResponseMessage());
        }
        try {
            try (InputStream in = conn.getInputStream()) {
                return IOUtils.toByteArray(in);
            }
        } finally {
            conn.disconnect();
        }
    }
}